Typed res

This commit is contained in:
Manav Rathi
2024-11-26 14:02:22 +05:30
parent 34a881115f
commit b2a9ebe3b8
2 changed files with 33 additions and 39 deletions

View File

@@ -4,7 +4,10 @@ import { boxSeal } from "@/base/crypto";
import log from "@/base/log";
import type { Collection } from "@/media/collection";
import { photosDialogZIndex } from "@/new/photos/components/utils/z-index";
import castGateway, { revokeAllCastTokens } from "@/new/photos/services/cast";
import castGateway, {
publicKeyForPairingCode,
revokeAllCastTokens,
} from "@/new/photos/services/cast";
import { loadCast } from "@/new/photos/utils/chromecast-sender";
import SingleInputForm, {
type SingleInputFormProps,
@@ -52,36 +55,34 @@ export const AlbumCastDialog: React.FC<AlbumCastDialogProps> = ({
setFieldError,
) => {
try {
await doCast(value.trim());
onClose();
} catch (e) {
if (e instanceof Error && e.message == "tv-not-found") {
setFieldError(t("tv_not_found"));
if (await doCast(value.trim())) {
onClose();
} else {
setFieldError(t("generic_error_retry"));
setFieldError(t("tv_not_found"));
}
} catch (e) {
log.error("Failed to cast", e);
setFieldError(t("generic_error_retry"));
}
};
const doCast = async (pin: string) => {
// Does the TV exist? have they advertised their existence?
const tvPublicKeyB64 = await castGateway.getPublicKey(pin);
if (!tvPublicKeyB64) {
throw new Error("tv-not-found");
}
// Find out the public key associated with the given pairing code (if
// indeed a device has published one).
const publicKey = await publicKeyForPairingCode(pin);
if (!publicKey) return false;
// Generate random id.
const castToken = uuidv4();
// Ok, they exist. let's give them the good stuff.
// Publish the payload so that the other end can use it.
const payload = JSON.stringify({
castToken: castToken,
collectionID: collection.id,
collectionKey: collection.key,
});
const encryptedPayload = await boxSeal(btoa(payload), tvPublicKeyB64);
const encryptedPayload = await boxSeal(btoa(payload), publicKey);
// Hey TV, we acknowlege you!
await castGateway.publishCastPayload(
pin,
encryptedPayload,

View File

@@ -1,9 +1,8 @@
import { authenticatedRequestHeaders } from "@/base/http";
import log from "@/base/log";
import { authenticatedRequestHeaders, ensureOk } from "@/base/http";
import { apiURL } from "@/base/origins";
import { ApiError } from "@ente/shared/error";
import HTTPService from "@ente/shared/network/HTTPService";
import { getToken } from "@ente/shared/storage/localStorage/helpers";
import { z } from "zod";
/**
* Revoke all existing outstanding cast tokens for the current user on remote.
@@ -14,28 +13,22 @@ export const revokeAllCastTokens = async () =>
headers: await authenticatedRequestHeaders(),
});
class CastGateway {
public async getPublicKey(code: string): Promise<string> {
let resp;
try {
const token = getToken();
resp = await HTTPService.get(
await apiURL(`/cast/device-info/${code}`),
undefined,
{
"X-Auth-Token": token,
},
);
} catch (e) {
if (e instanceof ApiError && e.httpStatusCode === 404) {
return "";
}
log.error("failed to getPublicKey", e);
throw e;
}
return resp.data.publicKey;
}
/**
* Fetch the public key (represented as a base64 string) associated with the
* given device / pairing {@link code} from remote, or `undefined` if there is
* no public key associated with the given code.
*/
export const publicKeyForPairingCode = async (code: string) => {
const res = await fetch(await apiURL(`/cast/device-info/${code}`), {
headers: await authenticatedRequestHeaders(),
});
if (res.status == 404) return undefined;
ensureOk(res);
return z.object({ publicKey: z.string() }).parse(await res.json())
.publicKey;
};
class CastGateway {
public async publishCastPayload(
code: string,
castPayload: string,