1
0
Fork 0
mirror of https://gitlab.com/bramw/baserow.git synced 2025-04-28 14:32:26 +00:00

Fix advanced workspace level audit log not being enabled in the UI.

This commit is contained in:
Nigel Gott 2023-09-05 14:01:23 +00:00
parent 9038cf9bfc
commit c83b2d91e5
No known key found for this signature in database
8 changed files with 83 additions and 17 deletions
enterprise
backend
src/baserow_enterprise/api/audit_log
tests/baserow_enterprise_tests
web-frontend/modules/baserow_enterprise
premium/backend/tests/baserow_premium_tests

View file

@ -58,10 +58,7 @@ def check_for_license_and_permissions_or_raise(
audit log entries. If not, an exception is raised. audit log entries. If not, an exception is raised.
""" """
if user.is_staff: if workspace_id is not None:
LicenseHandler.raise_if_user_doesnt_have_feature_instance_wide(AUDIT_LOG, user)
return True
elif workspace_id is not None:
workspace = CoreHandler().get_workspace(workspace_id) workspace = CoreHandler().get_workspace(workspace_id)
LicenseHandler.raise_if_user_doesnt_have_feature(AUDIT_LOG, user, workspace) LicenseHandler.raise_if_user_doesnt_have_feature(AUDIT_LOG, user, workspace)
CoreHandler().check_permissions( CoreHandler().check_permissions(
@ -71,7 +68,9 @@ def check_for_license_and_permissions_or_raise(
context=workspace, context=workspace,
) )
else: else:
raise PermissionDenied() LicenseHandler.raise_if_user_doesnt_have_feature_instance_wide(AUDIT_LOG, user)
if not user.is_staff:
raise PermissionDenied()
class AuditLogView(APIListingView): class AuditLogView(APIListingView):

View file

@ -549,6 +549,7 @@ def test_audit_log_can_export_to_csv_all_entries(
enterprise_data_fixture, enterprise_data_fixture,
synced_roles, synced_roles,
django_capture_on_commit_callbacks, django_capture_on_commit_callbacks,
stubbed_storage,
): ):
_, admin_token = enterprise_data_fixture.create_enterprise_admin_user_and_token() _, admin_token = enterprise_data_fixture.create_enterprise_admin_user_and_token()

View file

@ -12,6 +12,8 @@ from rest_framework.status import (
HTTP_404_NOT_FOUND, HTTP_404_NOT_FOUND,
) )
from baserow_enterprise.license_types import EnterpriseLicenseType
@pytest.mark.django_db @pytest.mark.django_db
@pytest.mark.parametrize("url_name", ["users", "action_types", "list"]) @pytest.mark.parametrize("url_name", ["users", "action_types", "list"])
@ -195,6 +197,55 @@ def test_workspace_audit_log_user_filter_returns_only_workspace_users(
} }
@pytest.mark.django_db
@override_settings(DEBUG=True)
@pytest.mark.parametrize("url_name", ["users", "action_types", "list"])
def test_staff_member_can_access_audit_log_for_their_own_workspace(
api_client,
enterprise_data_fixture,
stubbed_storage,
alternative_per_workspace_license_service,
url_name,
):
admin_user, admin_token = enterprise_data_fixture.create_user_and_token(
email="admin@test.com", is_staff=True
)
workspace = enterprise_data_fixture.create_workspace(user=admin_user)
alternative_per_workspace_license_service.restrict_user_license_to(
admin_user, EnterpriseLicenseType.type, workspace.id
)
response = api_client.get(
reverse(f"api:enterprise:audit_log:{url_name}")
+ f"?workspace_id={workspace.id}",
format="json",
HTTP_AUTHORIZATION=f"JWT {admin_token}",
)
assert response.status_code == HTTP_200_OK
@pytest.mark.django_db
@override_settings(DEBUG=True)
@pytest.mark.parametrize("url_name", ["users", "action_types", "list"])
def test_staff_member_cant_access_audit_log_for_own_workspace_without_license(
api_client,
enterprise_data_fixture,
stubbed_storage,
alternative_per_workspace_license_service,
url_name,
):
admin_user, admin_token = enterprise_data_fixture.create_user_and_token(
email="admin@test.com", is_staff=True
)
workspace = enterprise_data_fixture.create_workspace(user=admin_user)
response = api_client.get(
reverse(f"api:enterprise:audit_log:{url_name}")
+ f"?workspace_id={workspace.id}",
format="json",
HTTP_AUTHORIZATION=f"JWT {admin_token}",
)
assert response.status_code == HTTP_402_PAYMENT_REQUIRED
@pytest.mark.django_db @pytest.mark.django_db
@override_settings(DEBUG=True) @override_settings(DEBUG=True)
def test_workspace_audit_log_can_export_to_csv_filtered_entries( def test_workspace_audit_log_can_export_to_csv_filtered_entries(

View file

@ -1,6 +1,8 @@
from django.apps import apps from django.apps import apps
from django.test.utils import override_settings from django.test.utils import override_settings
from baserow_premium_tests.conftest import * # noqa: F403, F401
from baserow.core.apps import sync_operations_after_migrate from baserow.core.apps import sync_operations_after_migrate
# noinspection PyUnresolvedReferences # noinspection PyUnresolvedReferences

View file

@ -44,7 +44,7 @@ export default {
}, },
computed: { computed: {
deactivated() { deactivated() {
return !this.$hasFeature(EnterpriseFeatures.AUDIT_LOG) return !this.$hasFeature(EnterpriseFeatures.AUDIT_LOG, this.workspace.id)
}, },
hasPermission() { hasPermission() {
return this.$hasPermission( return this.$hasPermission(

View file

@ -8,7 +8,7 @@
"sidebarTooltip": "Your account has access to the enterprise features globally", "sidebarTooltip": "Your account has access to the enterprise features globally",
"rbac": "RBAC", "rbac": "RBAC",
"sso": "SSO", "sso": "SSO",
"deactivated": "Available in the advanced/enterprise version", "deactivated": "Available in advanced/enterprise",
"licenseDescription": "Viewers are free with Baserow Enterprise. If a user has any other role, in any workspace then they will use a paid seat automatically.", "licenseDescription": "Viewers are free with Baserow Enterprise. If a user has any other role, in any workspace then they will use a paid seat automatically.",
"overflowWarning": "You have too many non-viewer users and have used up all of your paid seats. Change users to become viewers on each workspaces members page." "overflowWarning": "You have too many non-viewer users and have used up all of your paid seats. Change users to become viewers on each workspaces members page."
}, },
@ -279,6 +279,6 @@
}, },
"auditLogSidebarWorkspace": { "auditLogSidebarWorkspace": {
"title": "Audit log", "title": "Audit log",
"deactivated": "Available in the advanced/enterprise version" "deactivated": "Available in advanced/enterprise"
} }
} }

View file

@ -121,18 +121,16 @@ export default {
layout: 'app', layout: 'app',
middleware: 'authenticated', middleware: 'authenticated',
asyncData({ app, error, route, store }) { asyncData({ app, error, route, store }) {
if (!app.$hasFeature(EnterpriseFeatures.AUDIT_LOG)) {
return error({
statusCode: 401,
message: 'Available in the advanced/enterprise version',
})
}
const workspaceId = route.params.workspaceId const workspaceId = route.params.workspaceId
? parseInt(route.params.workspaceId) ? parseInt(route.params.workspaceId)
: null : null
if (workspaceId) { if (workspaceId) {
if ( if (!app.$hasFeature(EnterpriseFeatures.AUDIT_LOG, workspaceId)) {
return error({
statusCode: 401,
message: 'Available in the advanced/enterprise version',
})
} else if (
!app.$hasPermission( !app.$hasPermission(
'workspace.list_audit_log_entries', 'workspace.list_audit_log_entries',
store.getters['workspace/get'](workspaceId), store.getters['workspace/get'](workspaceId),
@ -141,6 +139,11 @@ export default {
) { ) {
return error({ statusCode: 404, message: 'Page not found' }) return error({ statusCode: 404, message: 'Page not found' })
} }
} else if (!app.$hasFeature(EnterpriseFeatures.AUDIT_LOG)) {
return error({
statusCode: 401,
message: 'Available in the advanced/enterprise version',
})
} else if (!store.getters['auth/isStaff']) { } else if (!store.getters['auth/isStaff']) {
return error({ statusCode: 403, message: 'Forbidden.' }) return error({ statusCode: 403, message: 'Forbidden.' })
} }

View file

@ -50,13 +50,23 @@ class PerWorkspaceLicensePlugin(LicensePlugin):
def restrict_user_premium_to( def restrict_user_premium_to(
self, user: AbstractUser, workspace_ids_or_id: Union[int, List[int]] self, user: AbstractUser, workspace_ids_or_id: Union[int, List[int]]
):
self.restrict_user_license_to(
user, PremiumLicenseType.type, workspace_ids_or_id
)
def restrict_user_license_to(
self,
user: AbstractUser,
license_type: str,
workspace_ids_or_id: Union[int, List[int]],
): ):
if isinstance(workspace_ids_or_id, int): if isinstance(workspace_ids_or_id, int):
workspace_ids_or_id = [workspace_ids_or_id] workspace_ids_or_id = [workspace_ids_or_id]
self.per_workspace_licenses[user.id] = defaultdict(set) self.per_workspace_licenses[user.id] = defaultdict(set)
for workspace_id in workspace_ids_or_id: for workspace_id in workspace_ids_or_id:
self.per_workspace_licenses[user.id][workspace_id].add( self.per_workspace_licenses[user.id][workspace_id].add(
license_type_registry.get(PremiumLicenseType.type) license_type_registry.get(license_type)
) )