Allow refreshing Viaplay session tokens on existing accounts.
Add Tokens vernieuwen UI and strip Bearer prefix when saving accessToken.
This commit is contained in:
parent
f19c173369
commit
1c939acd59
3 changed files with 173 additions and 53 deletions
|
|
@ -72,6 +72,11 @@ export function ViaplayPanel({ onChanged }: { onChanged?: (o: ViaplayOverview) =
|
||||||
const [newAccessToken, setNewAccessToken] = useState("");
|
const [newAccessToken, setNewAccessToken] = useState("");
|
||||||
const [newProfileId, setNewProfileId] = useState("");
|
const [newProfileId, setNewProfileId] = useState("");
|
||||||
|
|
||||||
|
const [tokenEditId, setTokenEditId] = useState<string | null>(null);
|
||||||
|
const [editSession, setEditSession] = useState("");
|
||||||
|
const [editAccessToken, setEditAccessToken] = useState("");
|
||||||
|
const [editProfileId, setEditProfileId] = useState("");
|
||||||
|
|
||||||
const applySettings = useCallback(
|
const applySettings = useCallback(
|
||||||
(d: ViaplaySettings) => {
|
(d: ViaplaySettings) => {
|
||||||
setSettings(d);
|
setSettings(d);
|
||||||
|
|
@ -186,6 +191,55 @@ export function ViaplayPanel({ onChanged }: { onChanged?: (o: ViaplayOverview) =
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openTokenEdit(account: ViaplayAccount) {
|
||||||
|
setTokenEditId((id) => (id === account.id ? null : account.id));
|
||||||
|
setEditSession("");
|
||||||
|
setEditAccessToken("");
|
||||||
|
setEditProfileId("");
|
||||||
|
setErr(null);
|
||||||
|
setMsg(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function saveAccountTokens(account: ViaplayAccount) {
|
||||||
|
if (!editSession.trim() && !editAccessToken.trim() && !editProfileId.trim()) {
|
||||||
|
setErr("Plak minstens session, accessToken of profileId");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setBusy(true);
|
||||||
|
setErr(null);
|
||||||
|
setMsg(null);
|
||||||
|
try {
|
||||||
|
const body: Record<string, string> = {};
|
||||||
|
if (editSession.trim()) body.session = editSession.trim();
|
||||||
|
if (editAccessToken.trim()) body.accessToken = editAccessToken.trim();
|
||||||
|
if (editProfileId.trim()) body.profileId = editProfileId.trim();
|
||||||
|
const r = await fetch(`/api/v1/admin/scripts/viaplay/accounts/${account.id}`, {
|
||||||
|
method: "PATCH",
|
||||||
|
credentials: "include",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify(body),
|
||||||
|
});
|
||||||
|
const d = await r.json();
|
||||||
|
if (!r.ok) throw new Error(d.error?.message ?? "Tokens bijwerken mislukt");
|
||||||
|
applySettings(d);
|
||||||
|
setTokenEditId(null);
|
||||||
|
setEditSession("");
|
||||||
|
setEditAccessToken("");
|
||||||
|
setEditProfileId("");
|
||||||
|
const updated = (d.accounts as ViaplayAccount[] | undefined)?.find((a) => a.id === account.id);
|
||||||
|
const sub = updated?.subscriptionSummary;
|
||||||
|
setMsg(
|
||||||
|
sub
|
||||||
|
? `Tokens bijgewerkt · abonnement: ${sub}`
|
||||||
|
: "Tokens bijgewerkt — druk Check als abonnement nog ontbreekt"
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
setErr(String((e as Error).message ?? e));
|
||||||
|
} finally {
|
||||||
|
setBusy(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function removeAccount(account: ViaplayAccount) {
|
async function removeAccount(account: ViaplayAccount) {
|
||||||
if (!confirm(`Account “${account.label || account.email}” verwijderen?`)) return;
|
if (!confirm(`Account “${account.label || account.email}” verwijderen?`)) return;
|
||||||
setBusy(true);
|
setBusy(true);
|
||||||
|
|
@ -377,14 +431,18 @@ export function ViaplayPanel({ onChanged }: { onChanged?: (o: ViaplayOverview) =
|
||||||
{accounts.map((a) => (
|
{accounts.map((a) => (
|
||||||
<li
|
<li
|
||||||
key={a.id}
|
key={a.id}
|
||||||
|
style={{
|
||||||
|
padding: "0.6rem 0",
|
||||||
|
borderBottom: "1px solid var(--border, #333)",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flexWrap: "wrap",
|
flexWrap: "wrap",
|
||||||
gap: 8,
|
gap: 8,
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "space-between",
|
justifyContent: "space-between",
|
||||||
padding: "0.6rem 0",
|
|
||||||
borderBottom: "1px solid var(--border, #333)",
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ flex: "1 1 280px", minWidth: 0 }}>
|
<div style={{ flex: "1 1 280px", minWidth: 0 }}>
|
||||||
|
|
@ -417,7 +475,9 @@ export function ViaplayPanel({ onChanged }: { onChanged?: (o: ViaplayOverview) =
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{a.partnerName && a.subscriptionSummary && !a.subscriptionSummary.includes(a.partnerName) ? (
|
{a.partnerName &&
|
||||||
|
a.subscriptionSummary &&
|
||||||
|
!a.subscriptionSummary.includes(a.partnerName) ? (
|
||||||
<div className="muted" style={{ fontSize: "0.8rem", marginTop: 2 }}>
|
<div className="muted" style={{ fontSize: "0.8rem", marginTop: 2 }}>
|
||||||
Partner: {a.partnerName}
|
Partner: {a.partnerName}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -433,6 +493,9 @@ export function ViaplayPanel({ onChanged }: { onChanged?: (o: ViaplayOverview) =
|
||||||
<button type="button" disabled={busy} onClick={() => void probeAccounts(a.id)}>
|
<button type="button" disabled={busy} onClick={() => void probeAccounts(a.id)}>
|
||||||
Check
|
Check
|
||||||
</button>
|
</button>
|
||||||
|
<button type="button" disabled={busy} onClick={() => openTokenEdit(a)}>
|
||||||
|
{tokenEditId === a.id ? "Annuleren" : "Tokens vernieuwen"}
|
||||||
|
</button>
|
||||||
<button type="button" disabled={busy} onClick={() => void toggleAccount(a)}>
|
<button type="button" disabled={busy} onClick={() => void toggleAccount(a)}>
|
||||||
{a.enabled ? "Uitschakelen" : "Inschakelen"}
|
{a.enabled ? "Uitschakelen" : "Inschakelen"}
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -440,6 +503,62 @@ export function ViaplayPanel({ onChanged }: { onChanged?: (o: ViaplayOverview) =
|
||||||
Verwijderen
|
Verwijderen
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
{tokenEditId === a.id ? (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
marginTop: 10,
|
||||||
|
padding: "10px 12px",
|
||||||
|
borderRadius: 6,
|
||||||
|
border: "1px solid var(--border, #333)",
|
||||||
|
display: "grid",
|
||||||
|
gap: "0.75rem",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<p className="muted" style={{ margin: 0, fontSize: "0.85rem" }}>
|
||||||
|
Plak verse waarden uit de browser. Lege velden blijven ongewijzigd.
|
||||||
|
</p>
|
||||||
|
<label className="field">
|
||||||
|
session
|
||||||
|
<textarea
|
||||||
|
value={editSession}
|
||||||
|
onChange={(e) => setEditSession(e.target.value)}
|
||||||
|
rows={2}
|
||||||
|
disabled={busy}
|
||||||
|
placeholder="nieuw session-cookie (optioneel)"
|
||||||
|
style={{ fontFamily: "monospace", fontSize: "0.8rem" }}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label className="field">
|
||||||
|
accessToken
|
||||||
|
<textarea
|
||||||
|
value={editAccessToken}
|
||||||
|
onChange={(e) => setEditAccessToken(e.target.value)}
|
||||||
|
rows={2}
|
||||||
|
disabled={busy}
|
||||||
|
placeholder="nieuw accessToken (voor pakketinfo vereist)"
|
||||||
|
style={{ fontFamily: "monospace", fontSize: "0.8rem" }}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label className="field">
|
||||||
|
profileId (optioneel)
|
||||||
|
<input
|
||||||
|
value={editProfileId}
|
||||||
|
onChange={(e) => setEditProfileId(e.target.value)}
|
||||||
|
disabled={busy}
|
||||||
|
placeholder="nieuw profileId"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="btn-primary"
|
||||||
|
disabled={busy}
|
||||||
|
onClick={() => void saveAccountTokens(a)}
|
||||||
|
>
|
||||||
|
Tokens opslaan & Check
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,7 @@ export function createAccountStored(
|
||||||
const email = input.email.trim().toLowerCase();
|
const email = input.email.trim().toLowerCase();
|
||||||
if (!email) throw new Error("E-mail verplicht");
|
if (!email) throw new Error("E-mail verplicht");
|
||||||
const session = input.session?.trim();
|
const session = input.session?.trim();
|
||||||
const accessToken = input.accessToken?.trim();
|
const accessToken = input.accessToken?.trim().replace(/^Bearer\s+/i, "").trim();
|
||||||
if (!session || !accessToken) {
|
if (!session || !accessToken) {
|
||||||
throw new Error("session + accessToken verplicht");
|
throw new Error("session + accessToken verplicht");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -261,7 +261,8 @@ export async function updateViaplayAccount(
|
||||||
sessionEnc = encryptSecret(input.session.trim(), sessionSecret);
|
sessionEnc = encryptSecret(input.session.trim(), sessionSecret);
|
||||||
}
|
}
|
||||||
if (input.accessToken?.trim()) {
|
if (input.accessToken?.trim()) {
|
||||||
accessTokenEnc = encryptSecret(input.accessToken.trim(), sessionSecret);
|
const token = input.accessToken.trim().replace(/^Bearer\s+/i, "").trim();
|
||||||
|
accessTokenEnc = encryptSecret(token, sessionSecret);
|
||||||
}
|
}
|
||||||
if (input.profileId !== undefined) {
|
if (input.profileId !== undefined) {
|
||||||
profileId = input.profileId.trim() || undefined;
|
profileId = input.profileId.trim() || undefined;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue