网站首页 网站源码
website
站点相关全部源代码,隐藏了一些关于服务器的信息
using System.Collections.Immutable;
using System.Runtime.CompilerServices;
using System.Text.Json;
using Dpz.Core.MongodbAccess;
using Dpz.Core.Public.Entity.Auth;
using Microsoft.Extensions.Logging;
using MongoDB.Bson;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using OpenIddict.Abstractions;

namespace Dpz.Core.Auth.Service;

[Obsolete("use TokenStoreService")]
public sealed class DpzTokenStore(IRepository<DpzToken> repository, ILogger<DpzTokenStore> logger)
    : IOpenIddictTokenStore<DpzToken>
{
    public async ValueTask<long> CountAsync(CancellationToken cancellationToken)
    {
        logger.LogInformation("Counting tokens");
        return await repository.MongodbQueryable.LongCountAsync(
            cancellationToken: cancellationToken
        );
    }

    public async ValueTask<long> CountAsync<TResult>(
        Func<IQueryable<DpzToken>, IQueryable<TResult>> query,
        CancellationToken cancellationToken
    )
    {
        logger.LogInformation("Counting tokens with custom query");
        return await query(repository.MongodbQueryable)
            .LongCountAsync(cancellationToken: cancellationToken);
    }

    public async ValueTask CreateAsync(DpzToken token, CancellationToken cancellationToken)
    {
        logger.LogInformation("Creating token {Id}", token.Id);
        await repository.InsertAsync(token, cancellationToken);
    }

    public async ValueTask DeleteAsync(DpzToken token, CancellationToken cancellationToken)
    {
        logger.LogInformation("Deleting token {Id}", token.Id);
        await repository.DeleteAsync(token.Id, cancellationToken);
    }

    public IAsyncEnumerable<DpzToken> FindAsync(
        string? subject,
        string? client,
        string? status,
        string? type,
        CancellationToken cancellationToken
    )
    {
        logger.LogInformation(
            "Find tokens subject={Subject}, client={Client}, status={Status}, type={Type}",
            subject,
            client,
            status,
            type
        );
        var filter = Builders<DpzToken>.Filter.Empty;

        if (!string.IsNullOrWhiteSpace(subject))
        {
            filter &= Builders<DpzToken>.Filter.Eq(x => x.Subject, subject);
        }
        if (!string.IsNullOrWhiteSpace(client) && ObjectId.TryParse(client, out var appId))
        {
            filter &= Builders<DpzToken>.Filter.Eq(x => x.ApplicationId, appId);
        }
        if (!string.IsNullOrWhiteSpace(status))
        {
            filter &= Builders<DpzToken>.Filter.Eq(x => x.Status, status);
        }
        if (!string.IsNullOrWhiteSpace(type))
        {
            filter &= Builders<DpzToken>.Filter.Eq(x => x.Type, type);
        }

        return repository.SearchForAsync(filter, cancellationToken);
    }

    public IAsyncEnumerable<DpzToken> FindByApplicationIdAsync(
        string identifier,
        CancellationToken cancellationToken
    )
    {
        logger.LogInformation("Find tokens by application id {Identifier}", identifier);
        if (!ObjectId.TryParse(identifier, out var appId))
        {
            return AsyncEnumerable.Empty<DpzToken>();
        }
        var filter = Builders<DpzToken>.Filter.Eq(x => x.ApplicationId, appId);
        return repository.SearchForAsync(filter, cancellationToken);
    }

    public IAsyncEnumerable<DpzToken> FindByAuthorizationIdAsync(
        string identifier,
        CancellationToken cancellationToken
    )
    {
        logger.LogInformation("Find tokens by authorization id {Identifier}", identifier);
        if (!ObjectId.TryParse(identifier, out var authId))
        {
            return AsyncEnumerable.Empty<DpzToken>();
        }
        var filter = Builders<DpzToken>.Filter.Eq(x => x.AuthorizationId, authId);
        return repository.SearchForAsync(filter, cancellationToken);
    }

    public async ValueTask<DpzToken?> FindByIdAsync(
        string identifier,
        CancellationToken cancellationToken
    )
    {
        logger.LogInformation("Find token by id {Identifier}", identifier);
        if (ObjectId.TryParse(identifier, out var id))
        {
            return await repository.FindAsync(id, cancellationToken);
        }
        return null;
    }

    public async ValueTask<DpzToken?> FindByReferenceIdAsync(
        string identifier,
        CancellationToken cancellationToken
    )
    {
        logger.LogInformation("Find token by reference id {Identifier}", identifier);
        return await repository
            .SearchFor(x => x.ReferenceId == identifier)
            .FirstOrDefaultAsync(cancellationToken);
    }

    public IAsyncEnumerable<DpzToken> FindBySubjectAsync(
        string subject,
        CancellationToken cancellationToken
    )
    {
        logger.LogInformation("Find tokens by subject {Subject}", subject);
        var filter = Builders<DpzToken>.Filter.Eq(x => x.Subject, subject);
        return repository.SearchForAsync(filter, cancellationToken);
    }

    public async ValueTask<string?> GetApplicationIdAsync(
        DpzToken token,
        CancellationToken cancellationToken
    )
    {
        return await ValueTask.FromResult(token.ApplicationId.ToString());
    }

    public async ValueTask<TResult?> GetAsync<TState, TResult>(
        Func<IQueryable<DpzToken>, TState, IQueryable<TResult>> query,
        TState state,
        CancellationToken cancellationToken
    )
    {
        return await Task.FromResult(query(repository.MongodbQueryable, state).FirstOrDefault());
    }

    public async ValueTask<string?> GetAuthorizationIdAsync(
        DpzToken token,
        CancellationToken cancellationToken
    )
    {
        return await ValueTask.FromResult(token.AuthorizationId.ToString());
    }

    public async ValueTask<DateTimeOffset?> GetCreationDateAsync(
        DpzToken token,
        CancellationToken cancellationToken
    )
    {
        var result = token.CreationDate is { } dt
            ? new DateTimeOffset(DateTime.SpecifyKind(dt, DateTimeKind.Utc))
            : (DateTimeOffset?)null;
        return await ValueTask.FromResult(result);
    }

    public async ValueTask<DateTimeOffset?> GetExpirationDateAsync(
        DpzToken token,
        CancellationToken cancellationToken
    )
    {
        var result = token.ExpirationDate is { } dt
            ? new DateTimeOffset(DateTime.SpecifyKind(dt, DateTimeKind.Utc))
            : (DateTimeOffset?)null;
        return await ValueTask.FromResult(result);
    }

    public async ValueTask<string?> GetIdAsync(DpzToken token, CancellationToken cancellationToken)
    {
        return await ValueTask.FromResult(token.Id.ToString());
    }

    public async ValueTask<string?> GetPayloadAsync(
        DpzToken token,
        CancellationToken cancellationToken
    )
    {
        return await ValueTask.FromResult(token.Payload);
    }

    public async ValueTask<ImmutableDictionary<string, JsonElement>> GetPropertiesAsync(
        DpzToken token,
        CancellationToken cancellationToken
    )
    {
        if (token.Properties is null or { ElementCount: 0 })
        {
            return await ValueTask.FromResult(ImmutableDictionary<string, JsonElement>.Empty);
        }

        var json = token.Properties.ToJson();
        using var doc = JsonDocument.Parse(json);
        var builder = ImmutableDictionary.CreateBuilder<string, JsonElement>();
        foreach (var prop in doc.RootElement.EnumerateObject())
        {
            builder[prop.Name] = prop.Value.Clone();
        }
        return await ValueTask.FromResult(builder.ToImmutable());
    }

    public async ValueTask<DateTimeOffset?> GetRedemptionDateAsync(
        DpzToken token,
        CancellationToken cancellationToken
    )
    {
        var result = token.RedemptionDate is { } dt
            ? new DateTimeOffset(DateTime.SpecifyKind(dt, DateTimeKind.Utc))
            : (DateTimeOffset?)null;
        return await ValueTask.FromResult(result);
    }

    public async ValueTask<string?> GetReferenceIdAsync(
        DpzToken token,
        CancellationToken cancellationToken
    )
    {
        return await ValueTask.FromResult(token.ReferenceId);
    }

    public async ValueTask<string?> GetStatusAsync(
        DpzToken token,
        CancellationToken cancellationToken
    )
    {
        return await ValueTask.FromResult(token.Status);
    }

    public async ValueTask<string?> GetSubjectAsync(
        DpzToken token,
        CancellationToken cancellationToken
    )
    {
        return await ValueTask.FromResult(token.Subject);
    }

    public async ValueTask<string?> GetTypeAsync(
        DpzToken token,
        CancellationToken cancellationToken
    )
    {
        return await ValueTask.FromResult(token.Type);
    }

    public async ValueTask<DpzToken> InstantiateAsync(CancellationToken cancellationToken)
    {
        return await ValueTask.FromResult(new DpzToken { Id = ObjectId.GenerateNewId() });
    }

    public IAsyncEnumerable<DpzToken> ListAsync(
        int? count,
        int? offset,
        CancellationToken cancellationToken
    )
    {
        logger.LogInformation(
            "List tokens with pagination: offset={Offset}, count={Count}",
            offset,
            count
        );
        var options = new FindOptions<DpzToken>();
        if (offset.HasValue)
        {
            options.Skip = offset.Value;
        }
        if (count.HasValue)
        {
            options.Limit = count.Value;
        }

        return repository.SearchForAsync(
            Builders<DpzToken>.Filter.Empty,
            options,
            cancellationToken
        );
    }

    public async IAsyncEnumerable<TResult> ListAsync<TState, TResult>(
        Func<IQueryable<DpzToken>, TState, IQueryable<TResult>> query,
        TState state,
        [EnumeratorCancellation] CancellationToken cancellationToken
    )
    {
        logger.LogInformation("List tokens with custom query state={State}", state);
        var projected = query(repository.MongodbQueryable, state);
        await foreach (
            var element in projected.ToAsyncEnumerable().WithCancellation(cancellationToken)
        )
        {
            yield return element;
        }
    }

    public async ValueTask<long> PruneAsync(
        DateTimeOffset threshold,
        CancellationToken cancellationToken
    )
    {
        logger.LogInformation("Prune tokens threshold={Threshold}", threshold);
        var builder = Builders<DpzToken>.Filter;
        var filter = builder.Or(
            builder.Lt(x => x.ExpirationDate, threshold.UtcDateTime),
            builder.Lt(x => x.RedemptionDate, threshold.UtcDateTime)
        );
        var result = await repository.Collection.DeleteManyAsync(filter, cancellationToken);
        return result.DeletedCount;
    }

    public async ValueTask<long> RevokeAsync(
        string? subject,
        string? client,
        string? status,
        string? type,
        CancellationToken cancellationToken
    )
    {
        logger.LogInformation(
            "Revoke tokens subject={Subject}, client={Client}, status={Status}, type={Type}",
            subject,
            client,
            status,
            type
        );
        var builder = Builders<DpzToken>.Filter;
        var filter = builder.Empty;

        if (!string.IsNullOrWhiteSpace(subject))
        {
            filter &= builder.Eq(x => x.Subject, subject);
        }
        if (!string.IsNullOrWhiteSpace(client) && ObjectId.TryParse(client, out var appId))
        {
            filter &= builder.Eq(x => x.ApplicationId, appId);
        }
        if (!string.IsNullOrWhiteSpace(status))
        {
            filter &= builder.Eq(x => x.Status, status);
        }
        if (!string.IsNullOrWhiteSpace(type))
        {
            filter &= builder.Eq(x => x.Type, type);
        }

        var update = Builders<DpzToken>.Update.Set(
            x => x.Status,
            OpenIddictConstants.Statuses.Revoked
        );
        var result = await repository.Collection.UpdateManyAsync(
            filter,
            update,
            cancellationToken: cancellationToken
        );
        return result.ModifiedCount;
    }

    public async ValueTask<long> RevokeByApplicationIdAsync(
        string identifier,
        CancellationToken cancellationToken = new CancellationToken()
    )
    {
        logger.LogInformation("Revoke tokens by application id {Identifier}", identifier);
        if (!ObjectId.TryParse(identifier, out var appId))
        {
            return 0L;
        }
        var filter = Builders<DpzToken>.Filter.Eq(x => x.ApplicationId, appId);
        var update = Builders<DpzToken>.Update.Set(
            x => x.Status,
            OpenIddictConstants.Statuses.Revoked
        );
        var result = await repository.Collection.UpdateManyAsync(
            filter,
            update,
            cancellationToken: cancellationToken
        );
        return result.ModifiedCount;
    }

    public async ValueTask<long> RevokeByAuthorizationIdAsync(
        string identifier,
        CancellationToken cancellationToken
    )
    {
        logger.LogInformation("Revoke tokens by authorization id {Identifier}", identifier);
        if (!ObjectId.TryParse(identifier, out var authId))
        {
            return 0L;
        }
        var filter = Builders<DpzToken>.Filter.Eq(x => x.AuthorizationId, authId);
        var update = Builders<DpzToken>.Update.Set(
            x => x.Status,
            OpenIddictConstants.Statuses.Revoked
        );
        var result = await repository.Collection.UpdateManyAsync(
            filter,
            update,
            cancellationToken: cancellationToken
        );
        return result.ModifiedCount;
    }

    public async ValueTask<long> RevokeBySubjectAsync(
        string subject,
        CancellationToken cancellationToken = new CancellationToken()
    )
    {
        logger.LogInformation("Revoke tokens by subject {Subject}", subject);
        var filter = Builders<DpzToken>.Filter.Eq(x => x.Subject, subject);
        var update = Builders<DpzToken>.Update.Set(
            x => x.Status,
            OpenIddictConstants.Statuses.Revoked
        );
        var result = await repository.Collection.UpdateManyAsync(
            filter,
            update,
            cancellationToken: cancellationToken
        );
        return result.ModifiedCount;
    }

    public async ValueTask SetApplicationIdAsync(
        DpzToken token,
        string? identifier,
        CancellationToken cancellationToken
    )
    {
        if (ObjectId.TryParse(identifier, out var appId))
        {
            token.ApplicationId = appId;
        }
        await ValueTask.CompletedTask;
    }

    public async ValueTask SetAuthorizationIdAsync(
        DpzToken token,
        string? identifier,
        CancellationToken cancellationToken
    )
    {
        if (ObjectId.TryParse(identifier, out var authId))
        {
            token.AuthorizationId = authId;
        }
        await ValueTask.CompletedTask;
    }

    public async ValueTask SetCreationDateAsync(
        DpzToken token,
        DateTimeOffset? date,
        CancellationToken cancellationToken
    )
    {
        token.CreationDate = date?.UtcDateTime;
        await ValueTask.CompletedTask;
    }

    public async ValueTask SetExpirationDateAsync(
        DpzToken token,
        DateTimeOffset? date,
        CancellationToken cancellationToken
    )
    {
        token.ExpirationDate = date?.UtcDateTime;
        await ValueTask.CompletedTask;
    }

    public async ValueTask SetPayloadAsync(
        DpzToken token,
        string? payload,
        CancellationToken cancellationToken
    )
    {
        token.Payload = payload;
        await ValueTask.CompletedTask;
    }

    public async ValueTask SetPropertiesAsync(
        DpzToken token,
        ImmutableDictionary<string, JsonElement> properties,
        CancellationToken cancellationToken
    )
    {
        if (properties.Count == 0)
        {
            token.Properties = null;
            await ValueTask.CompletedTask;
            return;
        }

        var bson = new BsonDocument();
        foreach (var kv in properties)
        {
            bson[kv.Key] = BsonDocument.Parse(kv.Value.GetRawText());
        }
        token.Properties = bson;
        await ValueTask.CompletedTask;
    }

    public async ValueTask SetRedemptionDateAsync(
        DpzToken token,
        DateTimeOffset? date,
        CancellationToken cancellationToken
    )
    {
        token.RedemptionDate = date?.UtcDateTime;
        await ValueTask.CompletedTask;
    }

    public async ValueTask SetReferenceIdAsync(
        DpzToken token,
        string? identifier,
        CancellationToken cancellationToken
    )
    {
        token.ReferenceId = identifier;
        await ValueTask.CompletedTask;
    }

    public async ValueTask SetStatusAsync(
        DpzToken token,
        string? status,
        CancellationToken cancellationToken
    )
    {
        token.Status = status;
        await ValueTask.CompletedTask;
    }

    public async ValueTask SetSubjectAsync(
        DpzToken token,
        string? subject,
        CancellationToken cancellationToken
    )
    {
        token.Subject = subject;
        await ValueTask.CompletedTask;
    }

    public async ValueTask SetTypeAsync(
        DpzToken token,
        string? type,
        CancellationToken cancellationToken
    )
    {
        token.Type = type;
        await ValueTask.CompletedTask;
    }

    public async ValueTask UpdateAsync(DpzToken token, CancellationToken cancellationToken)
    {
        logger.LogInformation("Update token {Id}", token.Id);
        await repository.UpdateAsync(token, cancellationToken);
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

上述代码定义了一个名为 DpzTokenStore 的类,它实现了 IOpenIddictTokenStore<DpzToken> 接口。这个类主要用于管理和操作与 OpenIddict 相关的令牌(tokens),并与 MongoDB 数据库进行交互。以下是该类的主要功能和结构的详细解释:

主要功能

  1. 令牌计数:

    • CountAsync 方法用于计算存储中的令牌数量,可以选择性地根据自定义查询进行计数。
  2. 创建和删除令牌:

    • CreateAsync 方法用于在数据库中插入新的令牌。
    • DeleteAsync 方法用于根据令牌的 ID 删除令牌。
  3. 查找令牌:

    • FindAsync 方法根据多个条件(如 subject、client、status 和 type)查找令牌。
    • FindByApplicationIdAsyncFindByAuthorizationIdAsyncFindBySubjectAsync 方法用于根据特定的应用程序 ID、授权 ID 或主题查找令牌。
    • FindByIdAsyncFindByReferenceIdAsync 方法用于根据 ID 或引用 ID 查找单个令牌。
  4. 获取令牌属性:

    • 提供了一系列方法(如 GetApplicationIdAsyncGetAuthorizationIdAsyncGetCreationDateAsync 等)来获取令牌的不同属性。
  5. 令牌实例化:

    • InstantiateAsync 方法用于创建一个新的 DpzToken 实例。
  6. 列出令牌:

    • ListAsync 方法用于分页列出令牌,可以选择性地根据自定义查询进行列出。
  7. 令牌修剪和撤销:

    • PruneAsync 方法用于删除过期或已撤销的令牌。
    • RevokeAsync 和相关方法用于根据不同条件(如 subject、client、status 和 type)撤销令牌。
  8. 设置令牌属性:

    • 提供了一系列方法(如 SetApplicationIdAsyncSetAuthorizationIdAsyncSetCreationDateAsync 等)来设置令牌的不同属性。
  9. 日志记录:

    • 使用 ILogger 记录操作的详细信息,便于调试和监控。

代码结构

  • 构造函数:

    • DpzTokenStore 的构造函数接受一个 IRepository<DpzToken> 和一个 ILogger<DpzTokenStore>,用于数据库操作和日志记录。
  • 异步编程:

    • 该类中的大多数方法都是异步的,使用 ValueTaskIAsyncEnumerable 来提高性能和响应性。
  • MongoDB 操作:

    • 使用 MongoDB 的驱动程序(如 Builders<T>Filter)来构建查询和更新操作。

总结

DpzTokenStore 类是一个用于管理 OpenIddict 令牌的服务,提供了创建、查找、更新、删除和撤销令牌的功能,并与 MongoDB 数据库进行交互。它还包含了详细的日志记录,以便于监控和调试。该类的设计遵循了异步编程的最佳实践,以提高性能和响应性。

loading