Пример #1
0
def test_get_assets(client, add_charging_station_assets, use_owner_id,
                    num_assets):
    """
    Get assets, either for all users (our user here is admin, so is allowed to see all 7 assets) or for
    a unique one (prosumer user 2 has one asset ― "Test battery").
    """
    auth_token = get_auth_token(client, "*****@*****.**", "testtest")
    test_prosumer2_id = find_user_by_email("*****@*****.**").id

    query = {}
    if use_owner_id:
        query["owner_id"] = test_prosumer2_id

    get_assets_response = client.get(
        url_for("flexmeasures_api_v2_0.get_assets"),
        query_string=query,
        headers={
            "content-type": "application/json",
            "Authorization": auth_token
        },
    )
    print("Server responded with:\n%s" % get_assets_response.json)
    assert get_assets_response.status_code == 200
    assert len(get_assets_response.json) == num_assets

    battery = {}
    for asset in get_assets_response.json:
        if asset["name"] == "Test battery":
            battery = asset
    assert battery
    assert pd.Timestamp(
        battery["soc_datetime"]) == pd.Timestamp("2015-01-01T00:00:00+00:00")
    assert battery["owner_id"] == test_prosumer2_id
    assert battery["capacity_in_mw"] == 2
Пример #2
0
def test_user_crud_as_non_admin(client, as_prosumer, view):
    user_index = client.get(url_for("UserCrudUI:index"), follow_redirects=True)
    assert user_index.status_code == 403
    prosumer2_id = find_user_by_email("*****@*****.**").id
    user_page = client.get(url_for(f"UserCrudUI:{view}", id=prosumer2_id),
                           follow_redirects=True)
    assert user_page.status_code == 403
Пример #3
0
def setup_assets(db, setup_roles_users, setup_markets):
    """Make some asset types and add assets to known test users."""

    data_source = DataSource(name="Seita", type="demo script")
    db.session.add(data_source)

    db.session.add(
        AssetType(
            name="solar",
            is_producer=True,
            can_curtail=True,
            daily_seasonality=True,
            yearly_seasonality=True,
        )
    )
    db.session.add(
        AssetType(
            name="wind",
            is_producer=True,
            can_curtail=True,
            daily_seasonality=True,
            yearly_seasonality=True,
        )
    )

    test_prosumer = find_user_by_email("*****@*****.**")
    test_market = Market.query.filter_by(name="epex_da").one_or_none()

    for asset_name in ["wind-asset-1", "wind-asset-2", "solar-asset-1"]:
        asset = Asset(
            name=asset_name,
            asset_type_name="wind" if "wind" in asset_name else "solar",
            event_resolution=timedelta(minutes=15),
            capacity_in_mw=1,
            latitude=10,
            longitude=100,
            min_soc_in_mwh=0,
            max_soc_in_mwh=0,
            soc_in_mwh=0,
            unit="MW",
            market_id=test_market.id,
        )
        asset.owner = test_prosumer
        db.session.add(asset)

        # one day of test data (one complete sine curve)
        time_slots = pd.date_range(
            datetime(2015, 1, 1), datetime(2015, 1, 1, 23, 45), freq="15T"
        )
        values = [random() * (1 + np.sin(x / 15)) for x in range(len(time_slots))]
        for dt, val in zip(time_slots, values):
            p = Power(
                datetime=as_server_time(dt),
                horizon=parse_duration("PT0M"),
                value=val,
                data_source_id=data_source.id,
            )
            p.asset = asset
            db.session.add(p)
Пример #4
0
def delete_user_and_data(email: str):
    """
    Delete a user, which also deletes their data.
    """
    the_user = find_user_by_email(email)
    if the_user is None:
        print(f"Could not find user with email address '{email}' ...")
        return
    delete_user(the_user)
    app.db.session.commit()
Пример #5
0
def test_delete_user(app):
    """Assert user has assets and power measurements. Deleting removes all of that."""
    prosumer: User = find_user_by_email("*****@*****.**")
    num_users_before = User.query.count()
    user_assets_with_measurements_before = Asset.query.filter(
        Asset.owner_id == prosumer.id, Asset.asset_type_name.in_(["wind", "solar"])
    ).all()
    asset_ids = [asset.id for asset in user_assets_with_measurements_before]
    for asset_id in asset_ids:
        num_power_measurements = Power.query.filter(Power.asset_id == asset_id).count()
        assert num_power_measurements == 96
    delete_user(prosumer)
    assert find_user_by_email("*****@*****.**") is None
    user_assets_after = Asset.query.filter(Asset.owner_id == prosumer.id).all()
    assert len(user_assets_after) == 0
    assert User.query.count() == num_users_before - 1
    for asset_id in asset_ids:
        num_power_measurements = Power.query.filter(Power.asset_id == asset_id).count()
        assert num_power_measurements == 0
def test_edit_user(client):
    with UserContext("*****@*****.**") as supplier:
        supplier_auth_token = supplier.get_auth_token()  # supplier is no admin
        supplier_id = supplier.id
    with UserContext("*****@*****.**") as prosumer:
        prosumer_auth_token = prosumer.get_auth_token()  # prosumer is an admin
        prosumer_id = prosumer.id
    # without being the user themselves or an admin, the user cannot be edited
    user_edit_response = client.patch(
        url_for("flexmeasures_api_v2_0.patch_user", id=prosumer_id),
        headers={
            "content-type": "application/json",
            "Authorization": supplier_auth_token,
        },
        json={},
    )
    assert user_edit_response.status_code == 403
    user_edit_response = client.patch(
        url_for("flexmeasures_api_v2_0.patch_user", id=supplier_id),
        headers={"content-type": "application/json"},
        json={},
    )
    assert user_edit_response.status_code == 401
    # admin can deactivate supplier, other changes will be ignored
    # (id is in the Userschema of the API, but we ignore it)
    headers = {
        "content-type": "application/json",
        "Authorization": prosumer_auth_token
    }
    user_edit_response = client.patch(
        url_for("flexmeasures_api_v2_0.patch_user", id=supplier_id),
        headers=headers,
        json={
            "active": False,
            "id": 888
        },
    )
    print("Server responded with:\n%s" % user_edit_response.json)
    assert user_edit_response.status_code == 200
    assert user_edit_response.json["active"] is False
    supplier = find_user_by_email("*****@*****.**")
    assert supplier.active is False
    assert supplier.id == supplier_id
    # admin can edit themselves but not sensitive fields
    headers = {
        "content-type": "application/json",
        "Authorization": prosumer_auth_token
    }
    user_edit_response = client.patch(
        url_for("flexmeasures_api_v2_0.patch_user", id=prosumer_id),
        headers=headers,
        json={"active": False},
    )
    print("Server responded with:\n%s" % user_edit_response.json)
    assert user_edit_response.status_code == 403
Пример #7
0
def get_asset_post_data() -> dict:
    post_data = {
        "name": "Test battery 2",
        "unit": "MW",
        "capacity_in_mw": 3,
        "event_resolution": timedelta(minutes=10).seconds / 60,
        "latitude": 30.1,
        "longitude": 100.42,
        "asset_type_name": "battery",
        "owner_id": find_user_by_email("*****@*****.**").id,
        "market_id": Sensor.query.filter_by(name="epex_da").one_or_none().id,
    }
    return post_data
Пример #8
0
def test_reset_password(client, as_admin, requests_mock):
    """Test it does not fail (logic is tested in API tests) and displays an answer."""
    user2 = find_user_by_email("*****@*****.**", keep_in_session=False)
    requests_mock.patch(
        f"http://localhost//api/v3_0/users/{user2.id}/password-reset",
        status_code=200,
    )
    user_page = client.get(
        url_for("UserCrudUI:reset_password_for", id=user2.id),
        follow_redirects=True,
    )
    assert user_page.status_code == 200
    assert b"has been changed to a random password" in user_page.data
Пример #9
0
def delete_a_user(email: str, force: bool):
    """
    Delete a user & also their assets and data.
    """
    if not force:
        prompt = f"Delete user '{email}'?"
        click.confirm(prompt, abort=True)
    the_user = find_user_by_email(email)
    if the_user is None:
        print(f"Could not find user with email address '{email}' ...")
        return
    delete_user(the_user)
    db.session.commit()
Пример #10
0
def test_get_one_user(client, requesting_user, status_code):
    test_user2_id = find_user_by_email("*****@*****.**").id
    headers = {"content-type": "application/json"}
    if requesting_user:
        headers["Authorization"] = get_auth_token(client, requesting_user,
                                                  "testtest")

    get_user_response = client.get(
        url_for("UserAPI:get", id=test_user2_id),
        headers=headers,
    )
    print("Server responded with:\n%s" % get_user_response.data)
    assert get_user_response.status_code == status_code
    if status_code == 200:
        assert get_user_response.json["username"] == "Test Prosumer User 2"
Пример #11
0
def test_deactivate_user(client, as_admin, requests_mock):
    """Test it does not fail (logic is tested in API tests) and displays an answer."""
    user2 = find_user_by_email("*****@*****.**", keep_in_session=False)
    requests_mock.patch(
        f"http://localhost//api/v3_0/users/{user2.id}",
        status_code=200,
        json={"active": False},
    )
    # de-activate
    user_page = client.get(
        url_for("UserCrudUI:toggle_active", id=user2.id), follow_redirects=True
    )
    assert user_page.status_code == 200
    assert user2.username in str(user_page.data)
    assert b"new activation status is now False" in user_page.data
Пример #12
0
def test_add_asset(db, client, setup_assets, requests_mock, as_admin):
    """Add a new asset"""
    user = find_user_by_email("*****@*****.**")
    mock_asset = mock_asset_response(account_id=user.account.id, as_list=False)
    requests_mock.post(api_path_assets, status_code=201, json=mock_asset)
    response = client.post(
        url_for("AssetCrudUI:post", id="create"),
        follow_redirects=True,
        data=mock_api_data_as_form_input(mock_asset),
    )
    assert response.status_code == 200  # response is HTML form
    assert "html" in response.content_type
    assert b"Creation was successful" in response.data
    assert mock_asset["name"] in str(response.data)
    assert str(mock_asset["latitude"]) in str(response.data)
    assert str(mock_asset["longitude"]) in str(response.data)
def test_get_one_user(client):
    test_supplier_id = find_user_by_email("*****@*****.**").id
    headers = {
        "content-type":
        "application/json",
        "Authorization":
        get_auth_token(client, "*****@*****.**", "testtest"),
    }

    get_user_response = client.get(
        url_for("flexmeasures_api_v2_0.get_user", id=test_supplier_id),
        headers=headers,
    )
    print("Server responded with:\n%s" % get_user_response.data)
    assert get_user_response.status_code == 200
    assert get_user_response.json["username"] == "Test Supplier"
Пример #14
0
def test_edit_user(client):
    with UserContext("*****@*****.**") as user2:
        user2_auth_token = user2.get_auth_token()  # user2 is no admin
        user2_id = user2.id
    with UserContext("*****@*****.**") as admin:
        admin_auth_token = admin.get_auth_token()
        admin_id = admin.id
    # without being the user themselves or an admin, the user cannot be edited
    user_edit_response = client.patch(
        url_for("UserAPI:patch", id=admin_id),
        headers={
            "content-type": "application/json",
            "Authorization": user2_auth_token,
        },
        json={},
    )
    assert user_edit_response.status_code == 403
    user_edit_response = client.patch(
        url_for("UserAPI:patch", id=user2_id),
        headers={"content-type": "application/json"},
        json={},
    )
    assert user_edit_response.status_code == 401
    # admin can deactivate user2
    admin_headers = {
        "content-type": "application/json",
        "Authorization": admin_auth_token,
    }
    user_edit_response = client.patch(
        url_for("UserAPI:patch", id=user2_id),
        headers=admin_headers,
        json={"active": False},
    )
    print("Server responded with:\n%s" % user_edit_response.json)
    assert user_edit_response.status_code == 200
    assert user_edit_response.json["active"] is False
    user2 = find_user_by_email("*****@*****.**")
    assert user2.active is False
    assert user2.id == user2_id
    # admin can edit themselves but not sensitive fields
    user_edit_response = client.patch(
        url_for("UserAPI:patch", id=admin_id),
        headers=admin_headers,
        json={"active": False},
    )
    print("Server responded with:\n%s" % user_edit_response.json)
    assert user_edit_response.status_code == 403
Пример #15
0
def test_add_asset_with_new_owner(client, requests_mock, as_admin):
    """Test roundtrip and expect new user (new owner) in db"""
    mock_asset = mock_asset_response(owner_id=-1, as_list=False)
    requests_mock.post("http://localhost//api/v2_0/assets",
                       status_code=201,
                       json=mock_asset)
    new_user_email = "*****@*****.**"
    data = copy.deepcopy(mock_asset)
    data["new_owner_email"] = new_user_email
    response = client.post(
        url_for("AssetCrudUI:post", id="create"),
        follow_redirects=True,
        data=mock_api_data_as_form_input(data),
    )
    assert response.status_code == 200
    assert b"Creation was successful" in response.data
    assert find_user_by_email(new_user_email)
Пример #16
0
def test_asset_page(db, client, setup_assets, requests_mock,
                    as_prosumer_user1):
    user = find_user_by_email("*****@*****.**")
    asset = user.assets[0]
    db.session.expunge(user)
    mock_asset = mock_asset_response(as_list=False)
    mock_asset["latitude"] = asset.latitude
    mock_asset["longitude"] = asset.longitude

    requests_mock.get(f"{api_path_assets}/{asset.id}",
                      status_code=200,
                      json=mock_asset)
    asset_page = client.get(url_for("AssetCrudUI:get", id=asset.id),
                            follow_redirects=True)
    assert ("Edit asset %s" % mock_asset["name"]).encode() in asset_page.data
    assert str(mock_asset["latitude"]).encode() in asset_page.data
    assert str(mock_asset["longitude"]).encode() in asset_page.data
Пример #17
0
def test_asset_page(db, client, requests_mock, as_prosumer):
    prosumer = find_user_by_email("*****@*****.**")
    asset = prosumer.assets[0]
    db.session.expunge(prosumer)
    mock_asset = mock_asset_response(as_list=False)
    mock_asset["capacity_in_mw"] = asset.capacity_in_mw
    mock_asset["latitude"] = asset.latitude
    mock_asset["longitude"] = asset.longitude

    requests_mock.get(f"http://localhost//api/v2_0/asset/{asset.id}",
                      status_code=200,
                      json=mock_asset)
    asset_page = client.get(url_for("AssetCrudUI:get", id=asset.id),
                            follow_redirects=True)
    assert ("Edit asset %s" %
            mock_asset["display_name"]).encode() in asset_page.data
    assert str(mock_asset["capacity_in_mw"]).encode() in asset_page.data
    assert str(mock_asset["latitude"]).encode() in asset_page.data
    assert str(mock_asset["longitude"]).encode() in asset_page.data
def test_user_reset_password(app, client, sender):
    """
    Reset the password of supplier.
    Only the prosumer is allowed to do that (as admin).
    """
    with UserContext("*****@*****.**") as supplier:
        supplier_id = supplier.id
        old_password = supplier.password
    headers = {"content-type": "application/json"}
    if sender != "":
        headers["Authorization"] = (get_auth_token(client, sender,
                                                   "testtest"), )
    with app.mail.record_messages() as outbox:
        pwd_reset_response = client.patch(
            url_for("flexmeasures_api_v2_0.reset_user_password",
                    id=supplier_id),
            query_string={},
            headers=headers,
        )
        print("Server responded with:\n%s" % pwd_reset_response.json)

        if sender == "":
            assert pwd_reset_response.status_code == 401
            return

        if sender == "*****@*****.**":
            assert pwd_reset_response.status_code == 403
            return

        assert pwd_reset_response.status_code == 200

        supplier = find_user_by_email("*****@*****.**")
        assert len(outbox) == 2
        assert "has been reset" in outbox[0].subject
        pwd_reset_instructions = outbox[1]
        assert old_password != supplier.password
        assert "reset instructions" in pwd_reset_instructions.subject
        assert ("reset your password:\n\n%sreset/" % request.host_url
                in pwd_reset_instructions.body)
def test_user_reset_password(app, client, setup_inactive_user, sender):
    """
    Reset the password of User 2.
    Only the admin user and User 2 themselves are allowed to do that.
    """
    with UserContext("*****@*****.**") as user2:
        user2_id = user2.id
        old_password = user2.password
    headers = {"content-type": "application/json"}
    if sender != "":
        headers["Authorization"] = (get_auth_token(client, sender, "testtest"),)
    with app.mail.record_messages() as outbox:
        pwd_reset_response = client.patch(
            url_for("UserAPI:reset_user_password", id=user2_id),
            query_string={},
            headers=headers,
        )
        print("Server responded with:\n%s" % pwd_reset_response.json)

        if sender in ("", "*****@*****.**"):
            assert pwd_reset_response.status_code == 401
            return
        if sender == "*****@*****.**":
            assert pwd_reset_response.status_code == 403
            return

        assert pwd_reset_response.status_code == 200

        user2 = find_user_by_email("*****@*****.**")
        assert len(outbox) == 2
        assert "has been reset" in outbox[0].subject
        pwd_reset_instructions = outbox[1]
        assert old_password != user2.password
        assert "reset instructions" in pwd_reset_instructions.subject
        assert (
            "reset your password:\n\n%sreset/" % request.host_url
            in pwd_reset_instructions.body
        )
Пример #20
0
def test_get_assets_badauth(client, setup_api_test_data, use_auth):
    """
    Attempt to get assets with wrong or missing auth.
    """
    # the case without auth: authentication will fail
    headers = {"content-type": "application/json"}
    query = {}
    if use_auth:
        # in this case, we successfully authenticate, but fail authorization
        headers["Authorization"] = get_auth_token(
            client, "*****@*****.**", "testtest"
        )
        test_prosumer = find_user_by_email("*****@*****.**")
        query = {"account_id": test_prosumer.account.id}

    get_assets_response = client.get(
        url_for("AssetAPI:index"), query_string=query, headers=headers
    )
    print("Server responded with:\n%s" % get_assets_response.json)
    if use_auth:
        assert get_assets_response.status_code == 403
    else:
        assert get_assets_response.status_code == 401
Пример #21
0
 def __init__(self, user_email: str):
     self.the_user = find_user_by_email(user_email)