Skip to content

Commit

Permalink
Merge pull request #1330 from bcgov/block-api-for-deleted-tenant
Browse files Browse the repository at this point in the history
Improvements to Tenant Deletion
Gavinok authored Aug 29, 2024

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
2 parents 47fd017 + d7c0cdb commit 7611ce0
Showing 11 changed files with 121 additions and 16 deletions.
6 changes: 3 additions & 3 deletions charts/traction/templates/acapy/deployment.yaml
Original file line number Diff line number Diff line change
@@ -51,6 +51,9 @@ spec:
--endpoint https://{{ include "acapy.host" . }} \
--arg-file '/home/aries/argfile.yml' \
--plugin 'aries_cloudagent.messaging.jsonld' \
{{- if .Values.acapy.plugins.multitenantProvider }}
--plugin multitenant_provider.v1_0 \
{{- end }}
{{- if .Values.acapy.plugins.tractionInnkeeper }}
--plugin traction_plugins.traction_innkeeper.v1_0 \
--plugin-config-value traction_innkeeper.innkeeper_wallet.tenant_id=\"$(INNKEEPER_WALLET_TENANT_ID)\" \
@@ -62,9 +65,6 @@ spec:
{{- if .Values.acapy.plugins.connectionUpdate }}
--plugin connection_update.v1_0 \
{{- end }}
{{- if .Values.acapy.plugins.multitenantProvider }}
--plugin multitenant_provider.v1_0 \
{{- end }}
{{- if .Values.acapy.plugins.rpc }}
--plugin rpc.v1_0 \
{{- end }}
40 changes: 39 additions & 1 deletion plugins/traction_innkeeper/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions plugins/traction_innkeeper/pyproject.toml
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@ bcrypt = "^4.2.0"
mergedeep = "^1.3.4"
typing-extensions = "4.8.0"
anoncreds = "^0.2.0"
multitenant-provider = {git = "https://github.com/hyperledger/aries-acapy-plugins", rev = "0.12.2", subdirectory = "multitenant_provider"}

[tool.poetry.dev-dependencies]
black = "^24.8.0"
Original file line number Diff line number Diff line change
@@ -4,7 +4,6 @@
from typing import Optional, Union, List

from aries_cloudagent.core.profile import ProfileSession
from aries_cloudagent.ledger.base import LOGGER
from aries_cloudagent.messaging.models.base_record import BaseRecord, BaseRecordSchema
from aries_cloudagent.messaging.util import datetime_to_str, str_to_datetime
from aries_cloudagent.messaging.valid import UUIDFour
@@ -357,12 +356,19 @@ async def soft_delete(self, session: ProfileSession):
Soft delete the tenant record by setting its state to 'deleted'.
Note: This method should be called on an instance of the TenantRecord.
"""
# Delete api records
recs = await TenantAuthenticationApiRecord.query_by_tenant_id(
session, self.tenant_id
)
for rec in recs:
if rec.tenant_id == self.tenant_id:
await rec.delete_record(session)

if self.state != self.STATE_DELETED:
self.state = self.STATE_DELETED
self.deleted_at = datetime_to_str(datetime.utcnow())
await self.save(session, reason="Soft delete")


async def restore_deleted(self, session: ProfileSession):
"""
Un-soft-delete the tenant record by setting its state to 'active'.
Original file line number Diff line number Diff line change
@@ -25,6 +25,7 @@
from aries_cloudagent.version import __version__
from aries_cloudagent.wallet.error import WalletSettingsError
from aries_cloudagent.wallet.models.wallet_record import WalletRecord
from multitenant_provider.v1_0.routes import plugin_wallet_create_token
from marshmallow import fields, validate

from . import TenantManager
@@ -522,6 +523,30 @@ async def tenant_create_token(request: web.BaseRequest):
return web.json_response({"token": token})


@docs(
tags=["multitenancy"],
summary="Get auth token for a subwallet (innkeeper plugin override)",
)
@request_schema(CreateWalletTokenRequestSchema)
@response_schema(CreateWalletTokenResponseSchema(), 200, description="")
@error_handler
async def tenant_wallet_create_token(request: web.BaseRequest):
context: AdminRequestContext = request["context"]
wallet_id = request.match_info["wallet_id"]

mgr = context.inject(TenantManager)
profile = mgr.profile

# Tenants must always be fetch by their wallet id.
async with profile.session() as session:
rec = await TenantRecord.query_by_wallet_id(session, wallet_id)
LOGGER.debug("when creating token ", rec)
if rec.state == TenantRecord.STATE_DELETED:
raise web.HTTPUnauthorized(reason="Tenant is disabled")

return await plugin_wallet_create_token(request)


@docs(
tags=[SWAGGER_CATEGORY],
)
@@ -1029,8 +1054,26 @@ async def register(app: web.Application):
"/multitenancy/reservations/{reservation_id}/check-in", tenant_checkin
),
web.post("/multitenancy/tenant/{tenant_id}/token", tenant_create_token),
web.post(
"/multitenancy/wallet/{wallet_id}/token", tenant_wallet_create_token
),
]
)
# Find the endpoint for token creation that already exists and
# override it
for r in app.router.routes():
if r.method == "POST":
if (
r.resource
and r.resource.canonical == "/multitenancy/wallet/{wallet_id}/token"
):
LOGGER.info(
f"found route: {r.method} {r.resource.canonical} ({r.handler})"
)
LOGGER.info(f"... replacing current handler: {r.handler}")
r._handler = tenant_wallet_create_token
LOGGER.info(f"... with new handler: {r.handler}")
has_wallet_create_token = True
# routes that require a tenant token for the innkeeper wallet/tenant/agent.
# these require not only a tenant, but it has to be the innkeeper tenant!
app.add_routes(
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@
from aries_cloudagent.messaging.models.openapi import OpenAPISchema
from marshmallow import fields

from .models import ReservationRecord, TenantAuthenticationApiRecord
from .models import ReservationRecord, TenantAuthenticationApiRecord, TenantRecord


from . import TenantManager
@@ -114,7 +114,9 @@ async def refresh_registration_token(reservation_id: str, manager: TenantManager
)
except Exception as err:
LOGGER.error("Failed to retrieve reservation: %s", err)
raise ReservationException("Could not retrieve reservation record.") from err
raise ReservationException(
"Could not retrieve reservation record."
) from err

if reservation.state != ReservationRecord.STATE_APPROVED:
raise ReservationException("Only approved reservations can refresh tokens.")
@@ -140,7 +142,8 @@ async def refresh_registration_token(reservation_id: str, manager: TenantManager

LOGGER.info("Refreshed token for reservation %s", reservation_id)

return _pwd
return _pwd


def generate_api_key_data():
_key = str(uuid.uuid4().hex)
@@ -156,6 +159,8 @@ def generate_api_key_data():


async def create_api_key(rec: TenantAuthenticationApiRecord, manager: TenantManager):
if rec.state == TenantRecord.STATE_DELETED:
raise ValueError("Tenant is disabled")
async with manager.profile.session() as session:
_key, _salt, _hash = generate_api_key_data()
rec.api_key_token_salt = _salt.decode("utf-8")
2 changes: 1 addition & 1 deletion services/aca-py/ngrok-wait.sh
Original file line number Diff line number Diff line change
@@ -37,8 +37,8 @@ exec aca-py start \
--wallet-storage-config "{\"url\":\"${POSTGRESQL_HOST}:5432\",\"max_connections\":5, \"wallet_scheme\":\"${TRACTION_ACAPY_WALLET_SCHEME}\"}" \
--wallet-storage-creds "{\"account\":\"${POSTGRESQL_USER}\",\"password\":\"${POSTGRESQL_PASSWORD}\",\"admin_account\":\"${POSTGRESQL_USER}\",\"admin_password\":\"${POSTGRESQL_PASSWORD}\"}" \
--admin "0.0.0.0" ${TRACTION_ACAPY_ADMIN_PORT} \
--plugin multitenant_provider.v1_0 \
--plugin traction_plugins.traction_innkeeper.v1_0 \
--plugin basicmessage_storage.v1_0 \
--plugin connection_update.v1_0 \
--plugin multitenant_provider.v1_0 \
--plugin rpc.v1_0 \
Original file line number Diff line number Diff line change
@@ -52,6 +52,7 @@
{{ $t('common.deleted') }}
</span>
<RestoreTenant :id="data.tenant_id" :name="data.tenant_name" />
<DeleteTenant :tenant="data" unsuspendable />
</div>
</template>
</Column>
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@
{{ $t('tenants.settings.permanentDelete') }}
</label>
</div>
<div class="flex items-center my-2">
<div v-if="!props.unsuspendable" class="flex items-center my-2">
<RadioButton v-model="perminant" value="Soft" />
<label class="ml-2" for="">
{{ $t('tenants.settings.softDelete') }}
@@ -67,6 +67,7 @@ type DeletionAPI = 'Innkeeper' | 'Tenant';
const props = defineProps<{
tenant: TenantRecord;
api: DeletionAPI;
unsuspendable?: boolean;
}>();
const emit = defineEmits(['closed', 'success']);
@@ -82,12 +83,11 @@ const displayWarning = computed(() => {
if (perminant.value == 'Hard') return true;
else return false;
});
// toast.info("hello");
const toast = useToast();
type DeletionType = 'Hard' | 'Soft';
const perminant: Ref<DeletionType> = ref('Soft');
const perminant: Ref<DeletionType> = ref(props.unsuspendable ? 'Hard' : 'Soft');
const tenantDelete = async () => {
const tenantStore = useTenantStore();
@@ -119,7 +119,14 @@ async function handleDelete() {
await innkeeperDelete();
}
toast.success(
t('tenants.settings.confirmDeletionSuccess', [props.tenant.tenant_name])
t('tenants.settings.confirmDeletionSuccess', [
props.tenant.tenant_name,
t(
perminant.value == 'Hard'
? 'tenants.settings.deleted'
: 'tenants.settings.suspended'
),
])
);
emit('success');
emit('closed');
Original file line number Diff line number Diff line change
@@ -16,6 +16,7 @@
>
<ConfirmTenantDeletion
:tenant="props.tenant"
:unsuspendable="props.unsuspendable"
api="Innkeeper"
@success="$emit('success')"
@closed="handleClose"
@@ -38,6 +39,7 @@ defineEmits(['success']);
const props = defineProps<{
tenant: TenantRecord;
unsuspendable?: boolean;
}>();
const displayModal = ref(false);
6 changes: 4 additions & 2 deletions services/tenant-ui/frontend/src/plugins/i18n/locales/en.json
Original file line number Diff line number Diff line change
@@ -523,8 +523,10 @@
"canRegisterDid": "Tenant allowed to register public DID",
"confirmDeletion": "To confirm, type \"{tenantName}\" in the box below",
"confirmDeletionIncorrect": "Incorrect tenant name. Please confirm the correct name before deletion.",
"confirmDeletionSuccess": "Tenant {0} successfully marked as deleted",
"deleteTenant": "Delete Tenant",
"confirmDeletionSuccess": "Tenant {0} successfully marked as {1}",
"suspended": "suspended",
"deleted": "deleted",
"deleteTenant": "Suspend Tenant",
"permanentDelete": "Permanently Delete",
"softDelete": "Suspend Tenant",
"tenantDeletionWarning": ": This will delete all data associated with this tenant.",

0 comments on commit 7611ce0

Please sign in to comment.