Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions alembic/versions/a1b2c3d4e5f6_add_safety_data_user_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,26 +103,28 @@ def upgrade():
op.create_index(op.f('ix_users_to_grants_user_id'), 'users_to_grants', ['user_id'], unique=False)
op.create_index('ix_users_to_grants_user_grant_app', 'users_to_grants', ['user_id', 'grant_id', 'app'], unique=True)

# Insert default roles for safety_data (app = 1)
# Insert default roles and grants for safety_data (app = 1)
op.execute(f"""INSERT INTO roles (name, description, app, create_date)
VALUES ('anonymous', 'Anonymous user', {SAFETY_DATA_APP_ID}, now())""")
op.execute(f"""INSERT INTO roles (name, description, app, create_date)
VALUES ('authenticated', 'Basic authenticated user', {SAFETY_DATA_APP_ID}, now())""")
op.execute(f"""INSERT INTO roles (name, description, app, create_date)
VALUES ('admins', 'Safety-Data administrator', {SAFETY_DATA_APP_ID}, now())""")
op.execute(f"""INSERT INTO grants (name, description, app, create_date)
VALUES ('hot_spots_tab_grant', 'Access to hot spots tab', {SAFETY_DATA_APP_ID}, now())""")

add_builtin_safety_data_admin()


def downgrade():
# Remove default roles (app = 1 for safety_data)
for table in existing_tables:
op.execute(f"DELETE FROM {table} WHERE app = 1")

# Revert users_to_grants table
op.drop_table('users_to_grants')
op.drop_table('grants')

# Remove default roles (app = 1 for safety_data)
for table in existing_tables:
op.execute(f"DELETE FROM {table} WHERE app = 1")

# users_to_organizations
op.drop_index('ix_users_to_organizations_user_org_app', table_name='users_to_organizations')
op.create_index('ix_users_to_organizations_user_org', 'users_to_organizations', ['user_id', 'organization_id'], unique=True)
Expand Down
15 changes: 9 additions & 6 deletions anyway/views/user_system/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,10 @@ def decorated_view(*args, **kwargs):
user_email = current_user.email

# Check roles if specified (skip if None or empty list)
user_roles = {role.name for role in current_user.roles}
user_grants = {grant.name for grant in current_user.grants}
user_roles = {role.name for role in current_user.roles if role.app == app_id}
if not current_user.is_anonymous:
user_roles.add("authenticated")
user_grants = {grant.name for grant in current_user.grants if grant.app == app_id}
has_roles = set(roles).issubset(user_roles) if need_all_permissions else set(roles) & user_roles
has_grants = set(grants).issubset(user_grants) if need_all_permissions else set(grants) & user_grants
if has_roles and has_grants if need_all_permissions else (has_roles or has_grants):
Expand Down Expand Up @@ -263,18 +265,19 @@ def return_json_error(error_code: int, *argv) -> Response:


def an_oauth_authorize(provider: str) -> Response:
return oauth_authorize(provider, callback_endpoint="an_oauth_callback")
return oauth_authorize(provider, callback_endpoint="an_oauth_callback", app_id=ANYWAY_APP_ID)


def sd_oauth_authorize(provider: str) -> Response:
return oauth_authorize(provider, callback_endpoint="sd_oauth_callback")
return oauth_authorize(provider, callback_endpoint="sd_oauth_callback", app_id=SAFETY_DATA_APP_ID)


def oauth_authorize(provider: str, callback_endpoint: str) -> Response:
def oauth_authorize(provider: str, callback_endpoint: str, app_id: int) -> Response:
if provider != "google":
return return_json_error(Es.BR_ONLY_SUPPORT_GOOGLE)

if not current_user.is_anonymous:
# Allow login if user is anonymous OR logged into a different app
if not current_user.is_anonymous and current_user.app == app_id:
return return_json_error(Es.BR_USER_ALREADY_LOGGED_IN)

redirect_url_from_url = request.args.get("redirect_url", type=str)
Expand Down
8 changes: 5 additions & 3 deletions tests/test_flask.py
Original file line number Diff line number Diff line change
Expand Up @@ -339,10 +339,10 @@ def set_current_user_mock(get_curr_user: mock.MagicMock, user_id=USER_ID) -> Non
get_curr_user.return_value.email = USER_EMAIL
authenticated = mock.MagicMock()
authenticated.name = BE_CONST.Roles2Names.Authenticated.value
authenticated.app = 0
get_curr_user.return_value.roles = [authenticated]


@pytest.mark.single_test
@pytest.mark.user_system
def test_user_remove_from_role(app):
user_add_or_remove_role(app, "/user/remove_from_role")
Expand All @@ -360,7 +360,7 @@ def user_add_or_remove_role(app: FlaskClient, path: str) -> None:
set_mock_and_test_perm(app, current_user, path)

rv = post_json(app, path, json_data={"email": "a"})
assert_return_code_for_user_update(Errors.BR_NAME_MISSING, rv)
assert_return_code_for_user_update(Errors.BR_NAME_MISSING, rv, msg="2")

with patch("anyway.views.user_system.api.get_role_object") as get_role_object:
get_role_object.return_value = mock.MagicMock()
Expand All @@ -369,7 +369,7 @@ def user_add_or_remove_role(app: FlaskClient, path: str) -> None:
rv = post_json(
app, path, json_data={"role": BE_CONST.Roles2Names.Admins.value, "email": "a"}
)
assert_return_code_for_user_update(Errors.BR_USER_NOT_FOUND, rv, extra="a", msg="2")
assert_return_code_for_user_update(Errors.BR_USER_NOT_FOUND, rv, extra="a", msg="3")


def set_mock_and_test_perm(app, current_user, path):
Expand All @@ -378,6 +378,7 @@ def set_mock_and_test_perm(app, current_user, path):
assert_return_code_for_user_update(Errors.BR_BAD_AUTH, rv, msg="3")
role = mock.MagicMock()
role.name = BE_CONST.Roles2Names.Admins.value
role.app = 0
current_user.return_value.roles = [role]


Expand All @@ -402,6 +403,7 @@ def test_is_a_valid_role_name():
assert is_a_valid_role_name(url)


@pytest.mark.single_test
@pytest.mark.user_system
def test_user_change_user_active_mode(app: FlaskClient) -> None:
path = "/user/change_user_active_mode"
Expand Down
Loading