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; /// /// 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. /// /// /// A shared implementation that cannot reach its backend throws /// rather than reporting a miss, because a miss tells a polling client its secret is invalid. /// public interface IQuickConnectStore { /// /// Looks up a pending request by the secret handed to the initiating client. /// /// The request secret. /// A cancellation token. /// The request, or null when it is unknown or has expired. Task GetRequestBySecretAsync(string secret, CancellationToken cancellationToken = default); /// /// Looks up a pending request by the code shown to the user. /// /// The user facing code. /// A cancellation token. /// The request, or null when it is unknown or has expired. Task GetRequestByCodeAsync(string code, CancellationToken cancellationToken = default); /// /// Stores a new or updated request until , resolvable by both its secret /// and its code or by neither. A request already past is not stored. /// /// The request to store. /// The instant the request stops being resolvable. /// A cancellation token. /// A representing the asynchronous operation. Task SetRequestAsync(QuickConnectResult request, DateTime expiresUtc, CancellationToken cancellationToken = default); /// /// Atomically claims the sole right to authorize the request behind , 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. /// /// The request secret. /// The instant the claim lapses, after which the request can be authorized again. /// A cancellation token. /// true when this caller may go on to authorize the request; false when it is unknown, expired, already authorized or claimed elsewhere. Task TryClaimAuthorizationAsync(string secret, DateTime expiresUtc, CancellationToken cancellationToken = default); /// /// Stores the authentication minted for an authorized request until . /// /// The request secret the client exchanges. /// The authentication to hand out. /// The instant the authentication stops being exchangeable. /// A cancellation token. /// A representing the asynchronous operation. Task SetAuthorizationAsync(string secret, AuthenticationResult authenticationResult, DateTime expiresUtc, CancellationToken cancellationToken = default); /// /// Reads the authentication for . 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. /// /// The request secret. /// A cancellation token. /// The authentication, or null when the secret is unknown or has expired. Task GetAuthorizationAsync(string secret, CancellationToken cancellationToken = default); }