:drunk: AI did something
This commit is contained in:
@@ -1,6 +1,9 @@
|
|||||||
|
using MagicOnion;
|
||||||
|
using MagicOnion.Server;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using DysonNetwork.Shared.Cache;
|
using DysonNetwork.Shared.Cache;
|
||||||
using DysonNetwork.Shared.Models;
|
using DysonNetwork.Shared.Models;
|
||||||
|
using DysonNetwork.Shared.Services;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using NodaTime;
|
using NodaTime;
|
||||||
|
|
||||||
@@ -9,7 +12,7 @@ namespace DysonNetwork.Pass.Permission;
|
|||||||
public class PermissionService(
|
public class PermissionService(
|
||||||
AppDatabase db,
|
AppDatabase db,
|
||||||
ICacheService cache
|
ICacheService cache
|
||||||
)
|
) : ServiceBase<IPermissionService>, IPermissionService
|
||||||
{
|
{
|
||||||
private static readonly TimeSpan CacheExpiration = TimeSpan.FromMinutes(1);
|
private static readonly TimeSpan CacheExpiration = TimeSpan.FromMinutes(1);
|
||||||
|
|
||||||
@@ -195,4 +198,11 @@ public class PermissionService(
|
|||||||
Value = _SerializePermissionValue(value),
|
Value = _SerializePermissionValue(value),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async UnaryResult<bool> CheckPermission(string scope, string permission)
|
||||||
|
{
|
||||||
|
// Assuming the actor is always "user:current" for client-side checks
|
||||||
|
// You might need to adjust this based on how your client identifies itself
|
||||||
|
return await HasPermissionAsync("user:current", scope, permission);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -14,8 +14,9 @@
|
|||||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
||||||
<PackageReference Include="dotnet-etcd" Version="8.0.1" />
|
<PackageReference Include="dotnet-etcd" Version="8.0.1" />
|
||||||
<PackageReference Include="MagicOnion.Client" Version="7.0.5" />
|
<PackageReference Include="MagicOnion.Client" Version="7.0.5" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.3.0" />
|
<PackageReference Include="MagicOnion.Server" Version="7.0.5" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.3.0" />
|
|
||||||
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.6" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.6" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.6" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.6" />
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.6" />
|
||||||
|
|||||||
49
DysonNetwork.Shared/Permission/MagicOnionPermissionFilter.cs
Normal file
49
DysonNetwork.Shared/Permission/MagicOnionPermissionFilter.cs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
using MagicOnion.Server.Filters;
|
||||||
|
using MagicOnion.Server;
|
||||||
|
using DysonNetwork.Shared.Services;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using DysonNetwork.Shared.Models;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace DysonNetwork.Shared.Permission;
|
||||||
|
|
||||||
|
public class MagicOnionPermissionFilter : IMagicOnionFilter<RequiredPermissionAttribute>
|
||||||
|
{
|
||||||
|
private readonly IPermissionService _permissionService;
|
||||||
|
|
||||||
|
public MagicOnionPermissionFilter(IPermissionService permissionService)
|
||||||
|
{
|
||||||
|
_permissionService = permissionService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask Invoke(ServiceContext context, RequiredPermissionAttribute attribute, Func<ServiceContext, ValueTask> next)
|
||||||
|
{
|
||||||
|
var httpContext = context.GetHttpContext();
|
||||||
|
if (httpContext == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("HttpContext is not available in ServiceContext.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (httpContext.Items["CurrentUser"] is not Account currentUser)
|
||||||
|
{
|
||||||
|
throw new ReturnStatusException(MagicOnion.Grpc.StatusCode.PermissionDenied, "Unauthorized: Current user not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentUser.IsSuperuser)
|
||||||
|
{
|
||||||
|
await next(context);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var actor = $"user:{currentUser.Id}";
|
||||||
|
var hasPermission = await _permissionService.CheckPermission(actor, attribute.Scope, attribute.Permission);
|
||||||
|
|
||||||
|
if (!hasPermission)
|
||||||
|
{
|
||||||
|
throw new ReturnStatusException(MagicOnion.Grpc.StatusCode.PermissionDenied, $"Permission {attribute.Scope}/{attribute.Permission} was required.");
|
||||||
|
}
|
||||||
|
|
||||||
|
await next(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using MagicOnion.Server.Filters;
|
||||||
|
|
||||||
|
namespace DysonNetwork.Shared.Permission;
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
|
||||||
|
public class RequiredPermissionAttribute : MagicOnionFilterAttribute
|
||||||
|
{
|
||||||
|
public string Scope { get; }
|
||||||
|
public string Permission { get; }
|
||||||
|
|
||||||
|
public RequiredPermissionAttribute(string scope, string permission) : base(typeof(MagicOnionPermissionFilter))
|
||||||
|
{
|
||||||
|
Scope = scope;
|
||||||
|
Permission = permission;
|
||||||
|
Order = 999; // Ensure this runs after authentication filters
|
||||||
|
}
|
||||||
|
}
|
||||||
8
DysonNetwork.Shared/Services/IPermissionService.cs
Normal file
8
DysonNetwork.Shared/Services/IPermissionService.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using MagicOnion;
|
||||||
|
|
||||||
|
namespace DysonNetwork.Shared.Services;
|
||||||
|
|
||||||
|
public interface IPermissionService : IService<IPermissionService>
|
||||||
|
{
|
||||||
|
UnaryResult<bool> CheckPermission(string scope, string permission);
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using DysonNetwork.Sphere.Account;
|
using DysonNetwork.Shared.Models;
|
||||||
using DysonNetwork.Sphere.Connection.WebReader;
|
using DysonNetwork.Sphere.Connection.WebReader;
|
||||||
using DysonNetwork.Sphere.Discovery;
|
using DysonNetwork.Sphere.Discovery;
|
||||||
using DysonNetwork.Sphere.Post;
|
using DysonNetwork.Sphere.Post;
|
||||||
@@ -11,7 +11,7 @@ namespace DysonNetwork.Sphere.Activity;
|
|||||||
public class ActivityService(
|
public class ActivityService(
|
||||||
AppDatabase db,
|
AppDatabase db,
|
||||||
PublisherService pub,
|
PublisherService pub,
|
||||||
RelationshipService rels,
|
DysonNetwork.Shared.Services.IRelationshipService rels,
|
||||||
PostService ps,
|
PostService ps,
|
||||||
DiscoveryService ds
|
DiscoveryService ds
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using DysonNetwork.Shared.Models;
|
using DysonNetwork.Shared.Models;
|
||||||
|
using DysonNetwork.Sphere.Connection.WebReader;
|
||||||
using DysonNetwork.Sphere.Post;
|
using DysonNetwork.Sphere.Post;
|
||||||
using DysonNetwork.Sphere.Sticker;
|
using DysonNetwork.Sphere.Sticker;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@@ -9,15 +10,6 @@ using Microsoft.EntityFrameworkCore.Query;
|
|||||||
using NodaTime;
|
using NodaTime;
|
||||||
using Quartz;
|
using Quartz;
|
||||||
|
|
||||||
namespace DysonNetwork.Sphere;
|
|
||||||
|
|
||||||
public abstract class ModelBase
|
|
||||||
{
|
|
||||||
public Instant CreatedAt { get; set; }
|
|
||||||
public Instant UpdatedAt { get; set; }
|
|
||||||
public Instant? DeletedAt { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AppDatabase(
|
public class AppDatabase(
|
||||||
DbContextOptions<AppDatabase> options,
|
DbContextOptions<AppDatabase> options,
|
||||||
IConfiguration configuration
|
IConfiguration configuration
|
||||||
@@ -26,18 +18,18 @@ public class AppDatabase(
|
|||||||
public DbSet<CloudFile> Files { get; set; }
|
public DbSet<CloudFile> Files { get; set; }
|
||||||
public DbSet<CloudFileReference> FileReferences { get; set; }
|
public DbSet<CloudFileReference> FileReferences { get; set; }
|
||||||
|
|
||||||
public DbSet<Shared.Models.Publisher> Publishers { get; set; }
|
public DbSet<Publisher> Publishers { get; set; }
|
||||||
public DbSet<PublisherMember> PublisherMembers { get; set; }
|
public DbSet<PublisherMember> PublisherMembers { get; set; }
|
||||||
public DbSet<PublisherSubscription> PublisherSubscriptions { get; set; }
|
public DbSet<PublisherSubscription> PublisherSubscriptions { get; set; }
|
||||||
public DbSet<PublisherFeature> PublisherFeatures { get; set; }
|
public DbSet<PublisherFeature> PublisherFeatures { get; set; }
|
||||||
|
|
||||||
public DbSet<Post.Post> Posts { get; set; }
|
public DbSet<Post> Posts { get; set; }
|
||||||
public DbSet<PostReaction> PostReactions { get; set; }
|
public DbSet<PostReaction> PostReactions { get; set; }
|
||||||
public DbSet<PostTag> PostTags { get; set; }
|
public DbSet<PostTag> PostTags { get; set; }
|
||||||
public DbSet<PostCategory> PostCategories { get; set; }
|
public DbSet<PostCategory> PostCategories { get; set; }
|
||||||
public DbSet<PostCollection> PostCollections { get; set; }
|
public DbSet<PostCollection> PostCollections { get; set; }
|
||||||
|
|
||||||
public DbSet<Shared.Models.Realm> Realms { get; set; }
|
public DbSet<Realm> Realms { get; set; }
|
||||||
public DbSet<RealmMember> RealmMembers { get; set; }
|
public DbSet<RealmMember> RealmMembers { get; set; }
|
||||||
|
|
||||||
public DbSet<ChatRoom> ChatRooms { get; set; }
|
public DbSet<ChatRoom> ChatRooms { get; set; }
|
||||||
@@ -46,10 +38,10 @@ public class AppDatabase(
|
|||||||
public DbSet<RealtimeCall> ChatRealtimeCall { get; set; }
|
public DbSet<RealtimeCall> ChatRealtimeCall { get; set; }
|
||||||
public DbSet<MessageReaction> ChatReactions { get; set; }
|
public DbSet<MessageReaction> ChatReactions { get; set; }
|
||||||
|
|
||||||
public DbSet<Sticker.Sticker> Stickers { get; set; }
|
public DbSet<Sticker> Stickers { get; set; }
|
||||||
public DbSet<StickerPack> StickerPacks { get; set; }
|
public DbSet<StickerPack> StickerPacks { get; set; }
|
||||||
|
|
||||||
public DbSet<Shared.Models.Wallet> Wallets { get; set; }
|
public DbSet<Wallet> Wallets { get; set; }
|
||||||
public DbSet<WalletPocket> WalletPockets { get; set; }
|
public DbSet<WalletPocket> WalletPockets { get; set; }
|
||||||
public DbSet<Order> PaymentOrders { get; set; }
|
public DbSet<Order> PaymentOrders { get; set; }
|
||||||
public DbSet<Transaction> PaymentTransactions { get; set; }
|
public DbSet<Transaction> PaymentTransactions { get; set; }
|
||||||
@@ -59,8 +51,8 @@ public class AppDatabase(
|
|||||||
|
|
||||||
public DbSet<Subscription> WalletSubscriptions { get; set; }
|
public DbSet<Subscription> WalletSubscriptions { get; set; }
|
||||||
public DbSet<Coupon> WalletCoupons { get; set; }
|
public DbSet<Coupon> WalletCoupons { get; set; }
|
||||||
public DbSet<Connection.WebReader.WebArticle> WebArticles { get; set; }
|
public DbSet<WebArticle> WebArticles { get; set; }
|
||||||
public DbSet<Connection.WebReader.WebFeed> WebFeeds { get; set; }
|
public DbSet<WebFeed> WebFeeds { get; set; }
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
{
|
{
|
||||||
@@ -103,7 +95,7 @@ public class AppDatabase(
|
|||||||
.HasForeignKey(ps => ps.AccountId)
|
.HasForeignKey(ps => ps.AccountId)
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
modelBuilder.Entity<Post.Post>()
|
modelBuilder.Entity<Post>()
|
||||||
.HasGeneratedTsVectorColumn(p => p.SearchVector, "simple", p => new { p.Title, p.Description, p.Content })
|
.HasGeneratedTsVectorColumn(p => p.SearchVector, "simple", p => new { p.Title, p.Description, p.Content })
|
||||||
.HasIndex(p => p.SearchVector)
|
.HasIndex(p => p.SearchVector)
|
||||||
.HasMethod("GIN");
|
.HasMethod("GIN");
|
||||||
@@ -118,25 +110,25 @@ public class AppDatabase(
|
|||||||
.HasForeignKey(s => s.AppId)
|
.HasForeignKey(s => s.AppId)
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
modelBuilder.Entity<Post.Post>()
|
modelBuilder.Entity<Post>()
|
||||||
.HasOne(p => p.RepliedPost)
|
.HasOne(p => p.RepliedPost)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey(p => p.RepliedPostId)
|
.HasForeignKey(p => p.RepliedPostId)
|
||||||
.OnDelete(DeleteBehavior.Restrict);
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
modelBuilder.Entity<Post.Post>()
|
modelBuilder.Entity<Post>()
|
||||||
.HasOne(p => p.ForwardedPost)
|
.HasOne(p => p.ForwardedPost)
|
||||||
.WithMany()
|
.WithMany()
|
||||||
.HasForeignKey(p => p.ForwardedPostId)
|
.HasForeignKey(p => p.ForwardedPostId)
|
||||||
.OnDelete(DeleteBehavior.Restrict);
|
.OnDelete(DeleteBehavior.Restrict);
|
||||||
modelBuilder.Entity<Post.Post>()
|
modelBuilder.Entity<Post>()
|
||||||
.HasMany(p => p.Tags)
|
.HasMany(p => p.Tags)
|
||||||
.WithMany(t => t.Posts)
|
.WithMany(t => t.Posts)
|
||||||
.UsingEntity(j => j.ToTable("post_tag_links"));
|
.UsingEntity(j => j.ToTable("post_tag_links"));
|
||||||
modelBuilder.Entity<Post.Post>()
|
modelBuilder.Entity<Post>()
|
||||||
.HasMany(p => p.Categories)
|
.HasMany(p => p.Categories)
|
||||||
.WithMany(c => c.Posts)
|
.WithMany(c => c.Posts)
|
||||||
.UsingEntity(j => j.ToTable("post_category_links"));
|
.UsingEntity(j => j.ToTable("post_category_links"));
|
||||||
modelBuilder.Entity<Post.Post>()
|
modelBuilder.Entity<Post>()
|
||||||
.HasMany(p => p.Collections)
|
.HasMany(p => p.Collections)
|
||||||
.WithMany(c => c.Posts)
|
.WithMany(c => c.Posts)
|
||||||
.UsingEntity(j => j.ToTable("post_collection_links"));
|
.UsingEntity(j => j.ToTable("post_collection_links"));
|
||||||
@@ -189,11 +181,11 @@ public class AppDatabase(
|
|||||||
.HasForeignKey(m => m.SenderId)
|
.HasForeignKey(m => m.SenderId)
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
|
||||||
modelBuilder.Entity<Connection.WebReader.WebFeed>()
|
modelBuilder.Entity<WebFeed>()
|
||||||
.HasIndex(f => f.Url)
|
.HasIndex(f => f.Url)
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
|
|
||||||
modelBuilder.Entity<Connection.WebReader.WebArticle>()
|
modelBuilder.Entity<WebArticle>()
|
||||||
.HasIndex(a => a.Url)
|
.HasIndex(a => a.Url)
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
|
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ public partial class ChatController(AppDatabase db, ChatService cs, ChatRoomServ
|
|||||||
|
|
||||||
[HttpPost("{roomId:guid}/messages")]
|
[HttpPost("{roomId:guid}/messages")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[RequiredPermission("global", "chat.messages.create")]
|
[RequiredPermissionAttribute("global", "chat.messages.create")]
|
||||||
public async Task<ActionResult> SendMessage([FromBody] SendMessageRequest request, Guid roomId)
|
public async Task<ActionResult> SendMessage([FromBody] SendMessageRequest request, Guid roomId)
|
||||||
{
|
{
|
||||||
if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized();
|
if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized();
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Mvc;
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using DysonNetwork.Shared.Models;
|
using DysonNetwork.Shared.Models;
|
||||||
using DysonNetwork.Sphere.Account;
|
using DysonNetwork.Shared.Services;
|
||||||
using DysonNetwork.Sphere.Localization;
|
using DysonNetwork.Sphere.Localization;
|
||||||
using DysonNetwork.Sphere.Permission;
|
using DysonNetwork.Sphere.Permission;
|
||||||
using DysonNetwork.Sphere.Realm;
|
using DysonNetwork.Sphere.Realm;
|
||||||
@@ -20,11 +20,10 @@ public class ChatRoomController(
|
|||||||
FileReferenceService fileRefService,
|
FileReferenceService fileRefService,
|
||||||
ChatRoomService crs,
|
ChatRoomService crs,
|
||||||
RealmService rs,
|
RealmService rs,
|
||||||
ActionLogService als,
|
DysonNetwork.Shared.Services.IActionLogService als,
|
||||||
NotificationService nty,
|
DysonNetwork.Shared.Services.INotificationService nty,
|
||||||
RelationshipService rels,
|
DysonNetwork.Shared.Services.IRelationshipService rels,
|
||||||
IStringLocalizer<NotificationResource> localizer,
|
DysonNetwork.Shared.Services.IAccountEventService aes
|
||||||
AccountEventService aes
|
|
||||||
) : ControllerBase
|
) : ControllerBase
|
||||||
{
|
{
|
||||||
[HttpGet("{id:guid}")]
|
[HttpGet("{id:guid}")]
|
||||||
@@ -162,7 +161,7 @@ public class ChatRoomController(
|
|||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[RequiredPermission("global", "chat.create")]
|
[RequiredPermissionAttribute("global", "chat.create")]
|
||||||
public async Task<ActionResult<ChatRoom>> CreateChatRoom(ChatRoomRequest request)
|
public async Task<ActionResult<ChatRoom>> CreateChatRoom(ChatRoomRequest request)
|
||||||
{
|
{
|
||||||
if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized();
|
if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized();
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using DysonNetwork.Shared.Models;
|
using DysonNetwork.Shared.Models;
|
||||||
using DysonNetwork.Sphere.Account;
|
|
||||||
using DysonNetwork.Sphere.Chat.Realtime;
|
using DysonNetwork.Sphere.Chat.Realtime;
|
||||||
using DysonNetwork.Sphere.Connection;
|
using DysonNetwork.Sphere.Connection;
|
||||||
using DysonNetwork.Sphere.Storage;
|
using DysonNetwork.Sphere.Storage;
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public class WebReaderController(WebReaderService reader, ILogger<WebReaderContr
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[HttpDelete("link/cache")]
|
[HttpDelete("link/cache")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[RequiredPermission("maintenance", "cache.scrap")]
|
[RequiredPermissionAttribute("maintenance", "cache.scrap")]
|
||||||
public async Task<IActionResult> InvalidateCache([FromQuery] string url)
|
public async Task<IActionResult> InvalidateCache([FromQuery] string url)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(url))
|
if (string.IsNullOrEmpty(url))
|
||||||
@@ -76,7 +76,7 @@ public class WebReaderController(WebReaderService reader, ILogger<WebReaderContr
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[HttpDelete("cache/all")]
|
[HttpDelete("cache/all")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[RequiredPermission("maintenance", "cache.scrap")]
|
[RequiredPermissionAttribute("maintenance", "cache.scrap")]
|
||||||
public async Task<IActionResult> InvalidateAllCache()
|
public async Task<IActionResult> InvalidateAllCache()
|
||||||
{
|
{
|
||||||
await reader.InvalidateAllCachedPreviewsAsync();
|
await reader.InvalidateAllCachedPreviewsAsync();
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using DysonNetwork.Shared.Models;
|
using DysonNetwork.Shared.Models;
|
||||||
using DysonNetwork.Sphere.Account;
|
|
||||||
using DysonNetwork.Sphere.Publisher;
|
using DysonNetwork.Sphere.Publisher;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using DysonNetwork.Shared.Models;
|
using DysonNetwork.Shared.Models;
|
||||||
using DysonNetwork.Sphere.Account;
|
|
||||||
using DysonNetwork.Sphere.Permission;
|
using DysonNetwork.Sphere.Permission;
|
||||||
using DysonNetwork.Sphere.Publisher;
|
using DysonNetwork.Sphere.Publisher;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
@@ -14,7 +13,7 @@ namespace DysonNetwork.Sphere.Developer;
|
|||||||
public class DeveloperController(
|
public class DeveloperController(
|
||||||
AppDatabase db,
|
AppDatabase db,
|
||||||
PublisherService ps,
|
PublisherService ps,
|
||||||
ActionLogService als
|
DysonNetwork.Shared.Services.IActionLogService als
|
||||||
)
|
)
|
||||||
: ControllerBase
|
: ControllerBase
|
||||||
{
|
{
|
||||||
@@ -91,7 +90,7 @@ public class DeveloperController(
|
|||||||
|
|
||||||
[HttpPost("{name}/enroll")]
|
[HttpPost("{name}/enroll")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[RequiredPermission("global", "developers.create")]
|
[RequiredPermissionAttribute("global", "developers.create")]
|
||||||
public async Task<ActionResult<Shared.Models.Publisher>> EnrollDeveloperProgram(string name)
|
public async Task<ActionResult<Shared.Models.Publisher>> EnrollDeveloperProgram(string name)
|
||||||
{
|
{
|
||||||
if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized();
|
if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser) return Unauthorized();
|
||||||
|
|||||||
@@ -172,6 +172,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\DysonNetwork.Shared\DysonNetwork.Shared.csproj" />
|
<ProjectReference Include="..\DysonNetwork.Shared\DysonNetwork.Shared.csproj" />
|
||||||
|
<ProjectReference Include="..\DysonNetwork.Pass\DysonNetwork.Pass.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using DysonNetwork.Sphere.Auth;
|
using DysonNetwork.Pass.Auth;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
using DysonNetwork.Sphere.Auth.OidcProvider.Services;
|
using DysonNetwork.Pass.Auth;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using DysonNetwork.Shared.Models;
|
using DysonNetwork.Shared.Models;
|
||||||
using DysonNetwork.Sphere.Auth.OidcProvider.Responses;
|
using DysonNetwork.Pass.Auth;
|
||||||
using DysonNetwork.Sphere.Developer;
|
using DysonNetwork.Sphere.Developer;
|
||||||
|
|
||||||
namespace DysonNetwork.Sphere.Pages.Auth;
|
namespace DysonNetwork.Sphere.Pages.Auth;
|
||||||
|
|
||||||
public class AuthorizeModel(OidcProviderService oidcService, IConfiguration configuration) : PageModel
|
public class AuthorizeModel( DysonNetwork.Pass.Auth.OidcProvider.Services.OidcProviderService oidcService, IConfiguration configuration) : PageModel
|
||||||
{
|
{
|
||||||
[BindProperty(SupportsGet = true)] public string? ReturnUrl { get; set; }
|
[BindProperty(SupportsGet = true)] public string? ReturnUrl { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ using Microsoft.AspNetCore.Mvc;
|
|||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using DysonNetwork.Shared.Models;
|
using DysonNetwork.Shared.Models;
|
||||||
using DysonNetwork.Sphere.Auth;
|
using DysonNetwork.Pass.Auth;
|
||||||
using DysonNetwork.Sphere.Account;
|
using DysonNetwork.Shared.Services;
|
||||||
using DysonNetwork.Sphere.Connection;
|
using DysonNetwork.Sphere.Connection;
|
||||||
using NodaTime;
|
using NodaTime;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@@ -12,10 +12,10 @@ namespace DysonNetwork.Sphere.Pages.Auth
|
|||||||
{
|
{
|
||||||
public class LoginModel(
|
public class LoginModel(
|
||||||
AppDatabase db,
|
AppDatabase db,
|
||||||
AccountService accounts,
|
DysonNetwork.Shared.Services.IAccountService accounts,
|
||||||
AuthService auth,
|
DysonNetwork.Pass.Auth.AuthService auth,
|
||||||
GeoIpService geo,
|
GeoIpService geo,
|
||||||
ActionLogService als
|
DysonNetwork.Shared.Services.IActionLogService als
|
||||||
) : PageModel
|
) : PageModel
|
||||||
{
|
{
|
||||||
[BindProperty] [Required] public string Username { get; set; } = string.Empty;
|
[BindProperty] [Required] public string Username { get; set; } = string.Empty;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
@page "/web/auth/challenge/{id:guid}/select-factor"
|
@page "/web/auth/challenge/{id:guid}/select-factor"
|
||||||
@using DysonNetwork.Shared.Models
|
@using DysonNetwork.Shared.Models
|
||||||
@using DysonNetwork.Sphere.Account
|
|
||||||
@model DysonNetwork.Sphere.Pages.Auth.SelectFactorModel
|
@model DysonNetwork.Sphere.Pages.Auth.SelectFactorModel
|
||||||
@{
|
@{
|
||||||
ViewData["Title"] = "Select Authentication Method";
|
ViewData["Title"] = "Select Authentication Method";
|
||||||
|
|||||||
@@ -2,8 +2,8 @@ using DysonNetwork.Shared.Models;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using DysonNetwork.Sphere.Auth;
|
using DysonNetwork.Pass.Auth;
|
||||||
using DysonNetwork.Sphere.Account;
|
using DysonNetwork.Pass.Account;
|
||||||
|
|
||||||
namespace DysonNetwork.Sphere.Pages.Auth;
|
namespace DysonNetwork.Sphere.Pages.Auth;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
@page "/web/auth/challenge/{id:guid}/verify/{factorId:guid}"
|
@page "/web/auth/challenge/{id:guid}/verify/{factorId:guid}"
|
||||||
@using DysonNetwork.Shared.Models
|
@using DysonNetwork.Shared.Models
|
||||||
@using DysonNetwork.Sphere.Account
|
@using DysonNetwork.Shared.Models
|
||||||
@model DysonNetwork.Sphere.Pages.Auth.VerifyFactorModel
|
@model DysonNetwork.Sphere.Pages.Auth.VerifyFactorModel
|
||||||
@{
|
@{
|
||||||
ViewData["Title"] = "Verify Your Identity";
|
ViewData["Title"] = "Verify Your Identity";
|
||||||
|
|||||||
@@ -3,18 +3,18 @@ using DysonNetwork.Shared.Models;
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using DysonNetwork.Sphere.Auth;
|
using DysonNetwork.Shared.Services;
|
||||||
using DysonNetwork.Sphere.Account;
|
using DysonNetwork.Shared.Services;
|
||||||
using NodaTime;
|
using NodaTime;
|
||||||
|
|
||||||
namespace DysonNetwork.Sphere.Pages.Auth
|
namespace DysonNetwork.Sphere.Pages.Auth
|
||||||
{
|
{
|
||||||
public class VerifyFactorModel(
|
public class VerifyFactorModel(
|
||||||
AppDatabase db,
|
AppDatabase db,
|
||||||
AccountService accounts,
|
DysonNetwork.Shared.Services.IAccountService accountService,
|
||||||
AuthService auth,
|
DysonNetwork.Pass.Auth.AuthService authService,
|
||||||
ActionLogService als,
|
DysonNetwork.Shared.Services.IActionLogService actionLogService,
|
||||||
IConfiguration configuration,
|
IConfiguration configuration,
|
||||||
IHttpClientFactory httpClientFactory
|
IHttpClientFactory httpClientFactory
|
||||||
)
|
)
|
||||||
: PageModel
|
: PageModel
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@using DysonNetwork.Sphere.Auth
|
using DysonNetwork.Pass.Auth;
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="h-full">
|
<html lang="en" class="h-full">
|
||||||
<head>
|
<head>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
@page "/spells/{spellWord}"
|
@page "/spells/{spellWord}"
|
||||||
@using DysonNetwork.Sphere.Account
|
@using DysonNetwork.Shared.Models
|
||||||
@model DysonNetwork.Sphere.Pages.Spell.MagicSpellPage
|
@model DysonNetwork.Sphere.Pages.Spell.MagicSpellPage
|
||||||
|
|
||||||
@{
|
@{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using DysonNetwork.Sphere.Account;
|
using DysonNetwork.Shared.Models;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@@ -6,7 +6,7 @@ using NodaTime;
|
|||||||
|
|
||||||
namespace DysonNetwork.Sphere.Pages.Spell;
|
namespace DysonNetwork.Sphere.Pages.Spell;
|
||||||
|
|
||||||
public class MagicSpellPage(AppDatabase db, MagicSpellService spells) : PageModel
|
public class MagicSpellPage(AppDatabase db, DysonNetwork.Shared.Services.IMagicSpellService magicSpellService) : PageModel
|
||||||
{
|
{
|
||||||
[BindProperty] public MagicSpell? CurrentSpell { get; set; }
|
[BindProperty] public MagicSpell? CurrentSpell { get; set; }
|
||||||
[BindProperty] public string? NewPassword { get; set; }
|
[BindProperty] public string? NewPassword { get; set; }
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
using DysonNetwork.Shared.Services;
|
||||||
|
using MagicOnion;
|
||||||
|
|
||||||
|
namespace DysonNetwork.Sphere.Permission;
|
||||||
|
|
||||||
|
public class RequiredPermissionAttribute : TypeFilterAttribute
|
||||||
|
{
|
||||||
|
public RequiredPermissionAttribute(string scope, string permission) : base(typeof(RequiredPermissionFilter))
|
||||||
|
{
|
||||||
|
Arguments = new object[] { scope, permission };
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RequiredPermissionFilter : IAsyncActionFilter
|
||||||
|
{
|
||||||
|
private readonly IPermissionService _permissionService;
|
||||||
|
private readonly string _scope;
|
||||||
|
private readonly string _permission;
|
||||||
|
|
||||||
|
public RequiredPermissionFilter(IPermissionService permissionService, string scope, string permission)
|
||||||
|
{
|
||||||
|
_permissionService = permissionService;
|
||||||
|
_scope = scope;
|
||||||
|
_permission = permission;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
|
||||||
|
{
|
||||||
|
// Assuming the actor is always "user:current" for client-side checks
|
||||||
|
// You might need to adjust this based on how your client identifies itself
|
||||||
|
var hasPermission = await _permissionService.CheckPermission(_scope, _permission);
|
||||||
|
|
||||||
|
if (!hasPermission)
|
||||||
|
{
|
||||||
|
context.Result = new ForbidResult();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using DysonNetwork.Shared.Models;
|
using DysonNetwork.Shared.Models;
|
||||||
using DysonNetwork.Sphere.Account;
|
using DysonNetwork.Shared.Services;
|
||||||
using DysonNetwork.Sphere.Permission;
|
using DysonNetwork.Sphere.Permission;
|
||||||
using DysonNetwork.Sphere.Publisher;
|
using DysonNetwork.Sphere.Publisher;
|
||||||
using DysonNetwork.Sphere.Storage;
|
using DysonNetwork.Sphere.Storage;
|
||||||
@@ -19,8 +19,8 @@ public class PostController(
|
|||||||
AppDatabase db,
|
AppDatabase db,
|
||||||
PostService ps,
|
PostService ps,
|
||||||
PublisherService pub,
|
PublisherService pub,
|
||||||
RelationshipService rels,
|
DysonNetwork.Shared.Services.IRelationshipService rels,
|
||||||
ActionLogService als
|
DysonNetwork.Shared.Services.IActionLogService als
|
||||||
)
|
)
|
||||||
: ControllerBase
|
: ControllerBase
|
||||||
{
|
{
|
||||||
@@ -280,7 +280,7 @@ public class PostController(
|
|||||||
|
|
||||||
[HttpPost("{id:guid}/reactions")]
|
[HttpPost("{id:guid}/reactions")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[RequiredPermission("global", "posts.react")]
|
[RequiredPermissionAttribute("global", "posts.react")]
|
||||||
public async Task<ActionResult<PostReaction>> ReactPost(Guid id, [FromBody] PostReactionRequest request)
|
public async Task<ActionResult<PostReaction>> ReactPost(Guid id, [FromBody] PostReactionRequest request)
|
||||||
{
|
{
|
||||||
HttpContext.Items.TryGetValue("CurrentUser", out var currentUserValue);
|
HttpContext.Items.TryGetValue("CurrentUser", out var currentUserValue);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using DysonNetwork.Shared.Cache;
|
using DysonNetwork.Shared.Cache;
|
||||||
using DysonNetwork.Sphere.Account;
|
using DysonNetwork.Shared.Models;
|
||||||
using DysonNetwork.Sphere.Connection.WebReader;
|
using DysonNetwork.Sphere.Connection.WebReader;
|
||||||
using DysonNetwork.Sphere.Localization;
|
using DysonNetwork.Sphere.Localization;
|
||||||
using DysonNetwork.Sphere.Publisher;
|
using DysonNetwork.Sphere.Publisher;
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ var tusDiskStore = app.Services.GetRequiredService<TusDiskStore>();
|
|||||||
app.ConfigureAppMiddleware(builder.Configuration, tusDiskStore);
|
app.ConfigureAppMiddleware(builder.Configuration, tusDiskStore);
|
||||||
|
|
||||||
// Map gRPC services
|
// Map gRPC services
|
||||||
app.MapGrpcService<DysonNetwork.Sphere.Auth.AuthGrpcService>();
|
app.MapGrpcService<DysonNetwork.Pass.Auth.AuthGrpcService>();
|
||||||
app.MapGrpcService<DysonNetwork.Sphere.Account.AccountGrpcService>();
|
app.MapGrpcService<DysonNetwork.Pass.Account.AccountGrpcService>();
|
||||||
|
|
||||||
app.Run();
|
app.Run();
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using DysonNetwork.Shared.Models;
|
using DysonNetwork.Shared.Models;
|
||||||
using DysonNetwork.Sphere.Account;
|
|
||||||
using DysonNetwork.Sphere.Permission;
|
using DysonNetwork.Sphere.Permission;
|
||||||
using DysonNetwork.Sphere.Realm;
|
using DysonNetwork.Sphere.Realm;
|
||||||
using DysonNetwork.Sphere.Storage;
|
using DysonNetwork.Sphere.Storage;
|
||||||
@@ -17,7 +16,7 @@ public class PublisherController(
|
|||||||
AppDatabase db,
|
AppDatabase db,
|
||||||
PublisherService ps,
|
PublisherService ps,
|
||||||
FileReferenceService fileRefService,
|
FileReferenceService fileRefService,
|
||||||
ActionLogService als)
|
DysonNetwork.Shared.Services.IActionLogService als)
|
||||||
: ControllerBase
|
: ControllerBase
|
||||||
{
|
{
|
||||||
[HttpGet("{name}")]
|
[HttpGet("{name}")]
|
||||||
@@ -531,7 +530,7 @@ public class PublisherController(
|
|||||||
|
|
||||||
[HttpPost("{name}/features")]
|
[HttpPost("{name}/features")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[RequiredPermission("maintenance", "publishers.features")]
|
[RequiredPermissionAttribute("maintenance", "publishers.features")]
|
||||||
public async Task<ActionResult<PublisherFeature>> AddPublisherFeature(string name,
|
public async Task<ActionResult<PublisherFeature>> AddPublisherFeature(string name,
|
||||||
[FromBody] PublisherFeatureRequest request)
|
[FromBody] PublisherFeatureRequest request)
|
||||||
{
|
{
|
||||||
@@ -555,7 +554,7 @@ public class PublisherController(
|
|||||||
|
|
||||||
[HttpDelete("{name}/features/{flag}")]
|
[HttpDelete("{name}/features/{flag}")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[RequiredPermission("maintenance", "publishers.features")]
|
[RequiredPermissionAttribute("maintenance", "publishers.features")]
|
||||||
public async Task<ActionResult> RemovePublisherFeature(string name, string flag)
|
public async Task<ActionResult> RemovePublisherFeature(string name, string flag)
|
||||||
{
|
{
|
||||||
var publisher = await db.Publishers
|
var publisher = await db.Publishers
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using DysonNetwork.Shared.Cache;
|
using DysonNetwork.Shared.Cache;
|
||||||
using DysonNetwork.Shared.Models;
|
using DysonNetwork.Shared.Models;
|
||||||
using DysonNetwork.Sphere.Account;
|
using DysonNetwork.Pass.Account;
|
||||||
using DysonNetwork.Sphere.Localization;
|
using DysonNetwork.Sphere.Localization;
|
||||||
using DysonNetwork.Sphere.Post;
|
using DysonNetwork.Sphere.Post;
|
||||||
using DysonNetwork.Sphere.Storage;
|
using DysonNetwork.Sphere.Storage;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using DysonNetwork.Shared.Models;
|
using DysonNetwork.Shared.Models;
|
||||||
using DysonNetwork.Sphere.Account;
|
using DysonNetwork.Pass.Account;
|
||||||
using DysonNetwork.Sphere.Storage;
|
using DysonNetwork.Sphere.Storage;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
using DysonNetwork.Shared.Models;
|
using DysonNetwork.Shared.Models;
|
||||||
using DysonNetwork.Sphere.Account;
|
|
||||||
using DysonNetwork.Sphere.Localization;
|
using DysonNetwork.Sphere.Localization;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Localization;
|
using Microsoft.Extensions.Localization;
|
||||||
|
|
||||||
namespace DysonNetwork.Sphere.Realm;
|
namespace DysonNetwork.Sphere.Realm;
|
||||||
|
|
||||||
public class RealmService(AppDatabase db, NotificationService nty, IStringLocalizer<NotificationResource> localizer)
|
public class RealmService(AppDatabase db, DysonNetwork.Shared.Services.INotificationService nty, IStringLocalizer<NotificationResource> localizer)
|
||||||
{
|
{
|
||||||
public async Task SendInviteNotify(RealmMember member)
|
public async Task SendInviteNotify(RealmMember member)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using DysonNetwork.Sphere.Account;
|
using DysonNetwork.Pass.Account;
|
||||||
using DysonNetwork.Sphere.Permission;
|
using DysonNetwork.Sphere.Permission;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
@@ -122,7 +122,7 @@ public class AbuseReportController(
|
|||||||
|
|
||||||
[HttpPost("{id}/resolve")]
|
[HttpPost("{id}/resolve")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[RequiredPermission("safety", "reports.resolve")]
|
[RequiredPermissionAttribute("safety", "reports.resolve")]
|
||||||
[ProducesResponseType<AbuseReport>(StatusCodes.Status200OK)]
|
[ProducesResponseType<AbuseReport>(StatusCodes.Status200OK)]
|
||||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||||
public async Task<ActionResult<AbuseReport>> ResolveReport(Guid id, [FromBody] ResolveReportRequest request)
|
public async Task<ActionResult<AbuseReport>> ResolveReport(Guid id, [FromBody] ResolveReportRequest request)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using DysonNetwork.Sphere.Account;
|
using DysonNetwork.Pass.Account;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using NodaTime;
|
using NodaTime;
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ using DysonNetwork.Sphere.Discovery;
|
|||||||
using DysonNetwork.Sphere.Safety;
|
using DysonNetwork.Sphere.Safety;
|
||||||
using DysonNetwork.Sphere.Wallet.PaymentHandlers;
|
using DysonNetwork.Sphere.Wallet.PaymentHandlers;
|
||||||
using tusdotnet.Stores;
|
using tusdotnet.Stores;
|
||||||
|
using DysonNetwork.Shared.Etcd;
|
||||||
|
using DysonNetwork.Shared.Services;
|
||||||
|
|
||||||
namespace DysonNetwork.Sphere.Startup;
|
namespace DysonNetwork.Sphere.Startup;
|
||||||
|
|
||||||
@@ -206,6 +208,15 @@ public static class ServiceCollectionExtensions
|
|||||||
services.AddScoped<SafetyService>();
|
services.AddScoped<SafetyService>();
|
||||||
services.AddScoped<DiscoveryService>();
|
services.AddScoped<DiscoveryService>();
|
||||||
services.AddScoped<CustomAppService>();
|
services.AddScoped<CustomAppService>();
|
||||||
|
|
||||||
|
// Add MagicOnion services
|
||||||
|
services.AddMagicOnionService<IAccountService>();
|
||||||
|
services.AddMagicOnionService<IAccountEventService>();
|
||||||
|
services.AddMagicOnionService<IAccountUsernameService>();
|
||||||
|
services.AddMagicOnionService<IActionLogService>();
|
||||||
|
services.AddMagicOnionService<IMagicSpellService>();
|
||||||
|
services.AddMagicOnionService<INotificationService>();
|
||||||
|
services.AddMagicOnionService<IRelationshipService>();
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -271,7 +271,7 @@ public class StickerController(AppDatabase db, StickerService st) : ControllerBa
|
|||||||
public const int MaxStickersPerPack = 24;
|
public const int MaxStickersPerPack = 24;
|
||||||
|
|
||||||
[HttpPost("{packId:guid}/content")]
|
[HttpPost("{packId:guid}/content")]
|
||||||
[RequiredPermission("global", "stickers.create")]
|
[RequiredPermissionAttribute("global", "stickers.create")]
|
||||||
public async Task<IActionResult> CreateSticker(Guid packId, [FromBody] StickerRequest request)
|
public async Task<IActionResult> CreateSticker(Guid packId, [FromBody] StickerRequest request)
|
||||||
{
|
{
|
||||||
if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser)
|
if (HttpContext.Items["CurrentUser"] is not Shared.Models.Account currentUser)
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ public class FileController(
|
|||||||
|
|
||||||
[HttpPost("/maintenance/migrateReferences")]
|
[HttpPost("/maintenance/migrateReferences")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[RequiredPermission("maintenance", "files.references")]
|
[RequiredPermissionAttribute("maintenance", "files.references")]
|
||||||
public async Task<ActionResult> MigrateFileReferences()
|
public async Task<ActionResult> MigrateFileReferences()
|
||||||
{
|
{
|
||||||
await rms.ScanAndMigrateReferences();
|
await rms.ScanAndMigrateReferences();
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using DysonNetwork.Shared.Models;
|
using DysonNetwork.Shared.Models;
|
||||||
using DysonNetwork.Sphere.Account;
|
|
||||||
using EFCore.BulkExtensions;
|
using EFCore.BulkExtensions;
|
||||||
using Quartz;
|
using Quartz;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using DysonNetwork.Sphere.Permission;
|
using DysonNetwork.Pass.Permission;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using tusdotnet.Interfaces;
|
using tusdotnet.Interfaces;
|
||||||
@@ -10,7 +10,7 @@ using tusdotnet.Models.Configuration;
|
|||||||
|
|
||||||
namespace DysonNetwork.Sphere.Storage;
|
namespace DysonNetwork.Sphere.Storage;
|
||||||
|
|
||||||
public abstract class TusService
|
public class TusService(DefaultTusConfiguration config, ITusStore store)
|
||||||
{
|
{
|
||||||
public static DefaultTusConfiguration BuildConfiguration(ITusStore store) => new()
|
public static DefaultTusConfiguration BuildConfiguration(ITusStore store) => new()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using DysonNetwork.Shared.Models;
|
using DysonNetwork.Shared.Models;
|
||||||
using DysonNetwork.Sphere.Auth;
|
using DysonNetwork.Pass.Auth;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using DysonNetwork.Shared.Models;
|
using DysonNetwork.Shared.Models;
|
||||||
using DysonNetwork.Sphere.Account;
|
|
||||||
using DysonNetwork.Sphere.Localization;
|
using DysonNetwork.Sphere.Localization;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.EntityFrameworkCore.Storage;
|
using Microsoft.EntityFrameworkCore.Storage;
|
||||||
@@ -12,7 +11,7 @@ namespace DysonNetwork.Sphere.Wallet;
|
|||||||
public class PaymentService(
|
public class PaymentService(
|
||||||
AppDatabase db,
|
AppDatabase db,
|
||||||
WalletService wat,
|
WalletService wat,
|
||||||
NotificationService nty,
|
DysonNetwork.Shared.Services.INotificationService nty,
|
||||||
IStringLocalizer<NotificationResource> localizer
|
IStringLocalizer<NotificationResource> localizer
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using DysonNetwork.Shared.Cache;
|
using DysonNetwork.Shared.Cache;
|
||||||
using DysonNetwork.Shared.Models;
|
using DysonNetwork.Shared.Models;
|
||||||
using DysonNetwork.Sphere.Account;
|
using DysonNetwork.Shared.Services;
|
||||||
using DysonNetwork.Sphere.Localization;
|
using DysonNetwork.Sphere.Localization;
|
||||||
using DysonNetwork.Sphere.Storage;
|
using DysonNetwork.Sphere.Storage;
|
||||||
using DysonNetwork.Sphere.Wallet.PaymentHandlers;
|
using DysonNetwork.Sphere.Wallet.PaymentHandlers;
|
||||||
@@ -14,8 +14,8 @@ namespace DysonNetwork.Sphere.Wallet;
|
|||||||
public class SubscriptionService(
|
public class SubscriptionService(
|
||||||
AppDatabase db,
|
AppDatabase db,
|
||||||
PaymentService payment,
|
PaymentService payment,
|
||||||
AccountService accounts,
|
DysonNetwork.Shared.Services.IAccountService account,
|
||||||
NotificationService nty,
|
DysonNetwork.Shared.Services.INotificationService nty,
|
||||||
IStringLocalizer<NotificationResource> localizer,
|
IStringLocalizer<NotificationResource> localizer,
|
||||||
IConfiguration configuration,
|
IConfiguration configuration,
|
||||||
ICacheService cache,
|
ICacheService cache,
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ public class WalletController(AppDatabase db, WalletService ws, PaymentService p
|
|||||||
|
|
||||||
[HttpPost("balance")]
|
[HttpPost("balance")]
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[RequiredPermission("maintenance", "wallets.balance.modify")]
|
[RequiredPermissionAttribute("maintenance", "wallets.balance.modify")]
|
||||||
public async Task<ActionResult<Transaction>> ModifyWalletBalance([FromBody] WalletBalanceRequest request)
|
public async Task<ActionResult<Transaction>> ModifyWalletBalance([FromBody] WalletBalanceRequest request)
|
||||||
{
|
{
|
||||||
var wallet = await ws.GetWalletAsync(request.AccountId);
|
var wallet = await ws.GetWalletAsync(request.AccountId);
|
||||||
|
|||||||
Reference in New Issue
Block a user