ShareLinks plugin: guest share links for Jellyfin
Includes fix for redemption failing with DbUpdateConcurrencyException: change the guest password before applying the user policy, since UpdatePolicyAsync bumps the user's EF concurrency token and a stale instance then breaks ChangePassword.
Cette révision appartient à :
@@ -0,0 +1,70 @@
|
||||
using System;
|
||||
|
||||
namespace Jellyfin.Plugin.ShareLinks.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Persistent share-link record. Only the token hash is stored; the raw token
|
||||
/// never enters durable storage.
|
||||
/// </summary>
|
||||
public sealed class ShareLinkRecord
|
||||
{
|
||||
/// <summary>Gets or sets the share-link id.</summary>
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
|
||||
/// <summary>Gets or sets the HMAC hash of the token.</summary>
|
||||
public string TokenHash { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>Gets or sets the Jellyfin item id snapshot.</summary>
|
||||
public string ItemId { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>Gets or sets the Jellyfin item name snapshot.</summary>
|
||||
public string ItemNameSnapshot { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>Gets or sets the library id snapshot.</summary>
|
||||
public string? LibraryId { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the user id that created the link.</summary>
|
||||
public Guid? CreatedByUserId { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the UTC creation time.</summary>
|
||||
public DateTimeOffset CreatedAtUtc { get; set; } = DateTimeOffset.UtcNow;
|
||||
|
||||
/// <summary>Gets or sets the UTC redemption time, if any.</summary>
|
||||
public DateTimeOffset? RedeemedAtUtc { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the UTC expiry time.</summary>
|
||||
public DateTimeOffset ExpiresAtUtc { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the current lifecycle status.</summary>
|
||||
public ShareLinkStatus Status { get; set; } = ShareLinkStatus.Pending;
|
||||
|
||||
/// <summary>Gets or sets the guest user id associated with the link.</summary>
|
||||
public Guid? GuestUserId { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the guest user name associated with the link.</summary>
|
||||
public string? GuestUserName { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the access token id used by the guest session, if available.</summary>
|
||||
public string? AccessTokenId { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the device id used by the guest session, if available.</summary>
|
||||
public string? DeviceId { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the allowed tag snapshot, if any.</summary>
|
||||
public string? AllowedTag { get; set; }
|
||||
|
||||
/// <summary>Gets or sets a value indicating whether the link may be used once only.</summary>
|
||||
public bool OneUse { get; set; } = true;
|
||||
|
||||
/// <summary>Gets or sets the encrypted guest password, if one has been generated.</summary>
|
||||
public string? GuestPasswordEncrypted { get; set; }
|
||||
|
||||
/// <summary>Gets or sets a value indicating whether metadata was touched during cleanup.</summary>
|
||||
public bool MetadataTouched { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the number of cleanup attempts performed on this record.</summary>
|
||||
public int CleanupAttempts { get; set; }
|
||||
|
||||
/// <summary>Gets or sets the last cleanup error, if any.</summary>
|
||||
public string? CleanupError { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Jellyfin.Plugin.ShareLinks.Models;
|
||||
|
||||
/// <summary>Lifecycle state of a share link.</summary>
|
||||
public enum ShareLinkStatus
|
||||
{
|
||||
Pending = 0,
|
||||
Active = 1,
|
||||
Redeemed = 2,
|
||||
Expired = 3,
|
||||
Revoked = 4,
|
||||
Failed = 5,
|
||||
Redeeming = 6
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace Jellyfin.Plugin.ShareLinks.Models;
|
||||
|
||||
/// <summary>
|
||||
/// A freshly generated share token and its persisted hash.
|
||||
/// </summary>
|
||||
public sealed class ShareTokenMaterial
|
||||
{
|
||||
/// <summary>Gets or sets the raw token returned once to the caller.</summary>
|
||||
public string Token { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>Gets or sets the HMAC hash stored durably.</summary>
|
||||
public string TokenHash { get; set; } = string.Empty;
|
||||
}
|
||||
Référencer dans un nouveau ticket
Bloquer un utilisateur