Skip to content

Commit

Permalink
added api call to traction
Browse files Browse the repository at this point in the history
- refresh token
- send token back to frontend
Signed-off-by: Gurjeet Matharu <gmatharu12@gmail.com>
  • Loading branch information
gurjmatharu committed Oct 23, 2023
1 parent cba820e commit eb2cdc0
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from .config import InnkeeperWalletConfig
from .utils import (
approve_reservation,
refresh_registration_token,
create_api_key,
EndorserLedgerConfigSchema,
ReservationException,
Expand Down Expand Up @@ -91,15 +92,18 @@ async def wrapper(request):

return wrapper


# extending the CreateWalletTokenRequestSchema to allow for an API key
class CustomCreateWalletTokenRequestSchema(CreateWalletTokenRequestSchema):
"""Request schema for creating a wallet token."""

api_key = fields.Str(
description="API key for this wallet",
required=False,
example="3bd14a1e8fb645ddadf9913c0922ff3b",
)


class DefaultConfigValuesSchema(OpenAPISchema):
"""Response schema for default config values."""

Expand Down Expand Up @@ -136,6 +140,7 @@ class ReservationRequestSchema(OpenAPISchema):
example={"contact_phone": "555-555-5555"},
)


class ReservationResponseSchema(OpenAPISchema):
"""Response schema for tenant reservation."""

Expand Down Expand Up @@ -190,6 +195,10 @@ class ReservationApproveSchema(OpenAPISchema):
"""Request schema for tenant reservation approval."""


class ReservationRefreshSchema(OpenAPISchema):
"""Request schema for tenant reservation approval."""


class ReservationApproveResponseSchema(OpenAPISchema):
"""Response schema for tenant reservation approval."""

Expand Down Expand Up @@ -639,6 +648,25 @@ async def innkeeper_reservations_approve(request: web.BaseRequest):
return web.json_response({"reservation_pwd": _pwd})


@docs(
tags=[SWAGGER_CATEGORY],
)
@match_info_schema(ReservationIdMatchInfoSchema())
@request_schema(ReservationRefreshSchema())
@response_schema(ReservationApproveResponseSchema(), 200, description="")
@innkeeper_only
@error_handler
async def innkeeper_reservations_refresh_password(request: web.BaseRequest):
context: AdminRequestContext = request["context"]
reservation_id = request.match_info["reservation_id"]
mgr = context.inject(TenantManager)
try:
_pwd = await refresh_registration_token(reservation_id, mgr)
except ReservationException as err:
raise web.HTTPConflict(reason=str(err))
return web.json_response({"reservation_pwd": _pwd})


@docs(
tags=[SWAGGER_CATEGORY],
)
Expand Down Expand Up @@ -878,6 +906,10 @@ async def register(app: web.Application):
"/innkeeper/reservations/{reservation_id}/deny",
innkeeper_reservations_deny,
),
web.put(
"/innkeeper/reservations/{reservation_id}/refresh-password",
innkeeper_reservations_refresh_password,
),
web.get("/innkeeper/tenants/", innkeeper_tenants_list, allow_head=False),
web.get(
"/innkeeper/tenants/{tenant_id}", innkeeper_tenant_get, allow_head=False
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,46 @@ async def approve_reservation(
return _pwd


async def refresh_registration_token(reservation_id: str, manager: TenantManager):
"""
Invalidate the old token, generate a new token, and update the reservation record.
:return: new_token: the new refreshed token
"""
async with manager.profile.session() as session:
try:
reservation = await ReservationRecord.retrieve_by_reservation_id(
session, reservation_id, for_update=True
)
except Exception as err:
LOGGER.error("Failed to retrieve reservation: %s", err)
raise ReservationException("Could not retrieve reservation record.") from err

if reservation.state != ReservationRecord.STATE_APPROVED:
raise ReservationException("Only approved reservations can refresh tokens.")

# Generate new token data
_pwd = str(uuid.uuid4().hex) # This generates a new token
_salt = bcrypt.gensalt()
_hash = bcrypt.hashpw(_pwd.encode("utf-8"), _salt)

minutes = manager._config.reservation.expiry_minutes
_expiry = datetime.utcnow() + timedelta(minutes=minutes)

# Update the reservation record with the new token and related info
reservation.reservation_token_salt = _salt.decode("utf-8")
reservation.reservation_token_hash = _hash.decode("utf-8")
reservation.reservation_token_expiry = _expiry

try:
await reservation.save(session)
except Exception as err:
LOGGER.error("Failed to update reservation record: %s", err)
raise ReservationException("Could not update reservation record.") from err

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

return _pwd

def generate_api_key_data():
_key = str(uuid.uuid4().hex)
LOGGER.info(f"_key = {_key}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
<StatusChip :status="data.state" />
<RefreshPassword
v-if="data.state === 'approved'"
:id="data.id"
:id="data.reservation_id"
:email="data.contact_email"
@success="showModal"
/>
Expand Down
2 changes: 2 additions & 0 deletions services/tenant-ui/frontend/src/helpers/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ export const API_PATH = {
INNKEEPER_RESERVATIONS: '/innkeeper/reservations/',
INNKEEPER_RESERVATIONS_APPROVE: (id: string) =>
`/innkeeper/reservations/${id}/approve`,
INNKEEPER_RESERVATIONS_REFRESH_PASSWORD: (id: string) =>
`/innkeeper/reservations/${id}/refresh-password`,
INNKEEPER_RESERVATIONS_CONFIG: (id: string) =>
`/innkeeper/reservations/${id}/config`,
INNKEEPER_RESERVATIONS_DENY: (id: string) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,46 +178,42 @@ export const useInnkeeperTenantsStore = defineStore('innkeeperTenants', () => {
payload: any = {}
) {
console.log('> reservationStore.refreshCheckInPassword');
// error.value = null;
// loading.value = true;

// // Don't keep this as state, make sure the password doesn't hang around in memory
// let approveResponse: ApproveResponse = {};
// await acapyApi
// .putHttp(API_PATH.INNKEEPER_RESERVATIONS_APPROVE(id), payload)
// .then((res) => {
// approveResponse = res.data;
// })
// .catch((err) => {
// error.value = err;
// console.log(error.value);
// })
// .finally(() => {
// loading.value = false;
// });
// console.log('< reservationStore.approveReservation');

// if (error.value != null) {
// // throw error so $onAction.onError listeners can add their own handler
// throw error.value;
// }

// const trimUrl = window.location.origin;

// _sendStatusEmail({
// state: RESERVATION_STATUSES.APPROVED,
// contactEmail: email,
// reservationId: id,
// reservationPassword: approveResponse.reservation_pwd,
// serverUrl: trimUrl,
// serverUrlStatusRoute: `${trimUrl}/${RESERVATION_STATUS_ROUTE}`,
// contactName: name,
// });
error.value = null;
loading.value = true;

// return the reservation password
let test: { [key: string]: any } = {};
test.reservation_pwd = 'testing password';
return test;
// Don't keep this as state, make sure the password doesn't hang around in memory
let refreshResponse: ApproveResponse = {};
await acapyApi
.putHttp(API_PATH.INNKEEPER_RESERVATIONS_REFRESH_PASSWORD(id), payload)
.then((res) => {
refreshResponse = res.data;
})
.catch((err) => {
error.value = err;
console.log(error.value);
})
.finally(() => {
loading.value = false;
});
console.log('< reservationStore.refreshPassword');

if (error.value != null) {
throw error.value;
}

const trimUrl = window.location.origin;

_sendStatusEmail({
state: RESERVATION_STATUSES.APPROVED,
contactEmail: email,
reservationId: id,
reservationPassword: refreshResponse.reservation_pwd,
serverUrl: trimUrl,
serverUrlStatusRoute: `${trimUrl}/${RESERVATION_STATUS_ROUTE}`,
contactName: name,
});

return refreshResponse;
}

async function denyReservation(
Expand Down

0 comments on commit eb2cdc0

Please sign in to comment.