78 lines
4.5 KiB
C#
78 lines
4.5 KiB
C#
using System;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using MediaBrowser.Common.Extensions;
|
|
using MediaBrowser.Controller.Authentication;
|
|
using MediaBrowser.Model.QuickConnect;
|
|
|
|
namespace MediaBrowser.Controller.QuickConnect;
|
|
|
|
/// <summary>
|
|
/// Holds the state of in-flight quick connect requests. The three legs of a quick connect flow -
|
|
/// initiate, authorize and exchange - can each land on a different instance, so the state has to be
|
|
/// reachable from all of them.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// A shared implementation that cannot reach its backend throws <see cref="ServiceUnavailableException"/>
|
|
/// rather than reporting a miss, because a miss tells a polling client its secret is invalid.
|
|
/// </remarks>
|
|
public interface IQuickConnectStore
|
|
{
|
|
/// <summary>
|
|
/// Looks up a pending request by the secret handed to the initiating client.
|
|
/// </summary>
|
|
/// <param name="secret">The request secret.</param>
|
|
/// <param name="cancellationToken">A cancellation token.</param>
|
|
/// <returns>The request, or <c>null</c> when it is unknown or has expired.</returns>
|
|
Task<QuickConnectResult?> GetRequestBySecretAsync(string secret, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Looks up a pending request by the code shown to the user.
|
|
/// </summary>
|
|
/// <param name="code">The user facing code.</param>
|
|
/// <param name="cancellationToken">A cancellation token.</param>
|
|
/// <returns>The request, or <c>null</c> when it is unknown or has expired.</returns>
|
|
Task<QuickConnectResult?> GetRequestByCodeAsync(string code, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Stores a new or updated request until <paramref name="expiresUtc"/>, resolvable by both its secret
|
|
/// and its code or by neither. A request already past <paramref name="expiresUtc"/> is not stored.
|
|
/// </summary>
|
|
/// <param name="request">The request to store.</param>
|
|
/// <param name="expiresUtc">The instant the request stops being resolvable.</param>
|
|
/// <param name="cancellationToken">A cancellation token.</param>
|
|
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
|
Task SetRequestAsync(QuickConnectResult request, DateTime expiresUtc, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Atomically claims the sole right to authorize the request behind <paramref name="secret"/>, so
|
|
/// that two instances racing on one code cannot both mint an access token. The claim is never
|
|
/// released: a mint that failed after writing its token would otherwise be retried into a second one,
|
|
/// so a request whose authorization failed has to be started again.
|
|
/// </summary>
|
|
/// <param name="secret">The request secret.</param>
|
|
/// <param name="expiresUtc">The instant the claim lapses, after which the request can be authorized again.</param>
|
|
/// <param name="cancellationToken">A cancellation token.</param>
|
|
/// <returns><c>true</c> when this caller may go on to authorize the request; <c>false</c> when it is unknown, expired, already authorized or claimed elsewhere.</returns>
|
|
Task<bool> TryClaimAuthorizationAsync(string secret, DateTime expiresUtc, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Stores the authentication minted for an authorized request until <paramref name="expiresUtc"/>.
|
|
/// </summary>
|
|
/// <param name="secret">The request secret the client exchanges.</param>
|
|
/// <param name="authenticationResult">The authentication to hand out.</param>
|
|
/// <param name="expiresUtc">The instant the authentication stops being exchangeable.</param>
|
|
/// <param name="cancellationToken">A cancellation token.</param>
|
|
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
|
|
Task SetAuthorizationAsync(string secret, AuthenticationResult authenticationResult, DateTime expiresUtc, CancellationToken cancellationToken = default);
|
|
|
|
/// <summary>
|
|
/// Reads the authentication for <paramref name="secret"/>. The read does not consume it, so a client
|
|
/// that retries an exchange gets the same access token for as long as the authentication lives.
|
|
/// </summary>
|
|
/// <param name="secret">The request secret.</param>
|
|
/// <param name="cancellationToken">A cancellation token.</param>
|
|
/// <returns>The authentication, or <c>null</c> when the secret is unknown or has expired.</returns>
|
|
Task<AuthenticationResult?> GetAuthorizationAsync(string secret, CancellationToken cancellationToken = default);
|
|
}
|