:drunk: AI trying to fix bugs

This commit is contained in:
2025-07-06 21:15:30 +08:00
parent 3391c08c04
commit 7d1f096e87
70 changed files with 681 additions and 66945 deletions

View File

@ -89,6 +89,62 @@ namespace DysonNetwork.Common.Clients
response.EnsureSuccessStatusCode();
}
public async Task DeleteResourceReferencesAsync(string resourceId, string? usage = null)
{
var url = $"api/filereferences/resource/{resourceId}";
if (!string.IsNullOrEmpty(usage))
{
url += $"?usage={Uri.EscapeDataString(usage)}";
}
var response = await _httpClient.DeleteAsync(url);
response.EnsureSuccessStatusCode();
}
public async Task<List<CloudFileReference>> GetFileReferencesAsync(string fileId)
{
var response = await _httpClient.GetAsync($"api/filereferences/file/{fileId}");
response.EnsureSuccessStatusCode();
await using var stream = await response.Content.ReadAsStreamAsync();
var references = await JsonSerializer.DeserializeAsync<List<CloudFileReference>>(stream, _jsonOptions);
return references ?? new List<CloudFileReference>();
}
public async Task<List<CloudFileReference>> GetResourceReferencesAsync(string resourceId, string? usage = null)
{
var url = $"api/filereferences/resource/{resourceId}";
if (!string.IsNullOrEmpty(usage))
{
url += $"?usage={Uri.EscapeDataString(usage)}";
}
var response = await _httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
await using var stream = await response.Content.ReadAsStreamAsync();
var references = await JsonSerializer.DeserializeAsync<List<CloudFileReference>>(stream, _jsonOptions);
return references ?? new List<CloudFileReference>();
}
public async Task<bool> HasReferencesAsync(string fileId)
{
var response = await _httpClient.GetAsync($"api/filereferences/file/{fileId}/exists");
return response.IsSuccessStatusCode;
}
public async Task UpdateReferenceExpirationAsync(string referenceId, Instant? expiredAt)
{
var request = new { ExpiredAt = expiredAt };
var content = new StringContent(
JsonSerializer.Serialize(request, _jsonOptions),
Encoding.UTF8,
"application/json");
var response = await _httpClient.PutAsync($"api/filereferences/{referenceId}/expiration", content);
response.EnsureSuccessStatusCode();
}
public void Dispose()
{
_httpClient?.Dispose();

View File

@ -35,24 +35,30 @@ namespace DysonNetwork.Common.Clients
return file;
}
public async Task<Stream> DownloadFileAsync(string fileId)
public async Task<Stream> GetFileStreamAsync(string fileId)
{
if (string.IsNullOrEmpty(fileId))
throw new ArgumentNullException(nameof(fileId));
var response = await _httpClient.GetAsync($"api/files/{fileId}/download");
response.EnsureSuccessStatusCode();
return await response.Content.ReadAsStreamAsync();
var stream = await response.Content.ReadAsStreamAsync();
if (stream == null)
throw new InvalidOperationException("Failed to read file stream from response.");
return stream;
}
public async Task<CloudFile> UploadFileAsync(Stream fileStream, string fileName, string contentType, string? folderId = null)
public async Task<CloudFile> UploadFileAsync(Stream fileStream, string fileName, string? contentType = null)
{
using var content = new MultipartFormDataContent();
var fileContent = new StreamContent(fileStream);
content.Add(fileContent, "file", fileName);
if (!string.IsNullOrEmpty(folderId))
if (!string.IsNullOrEmpty(contentType))
{
content.Add(new StringContent(folderId), "folderId");
fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentType);
}
content.Add(fileContent, "file", fileName);
var response = await _httpClient.PostAsync("api/files/upload", content);
response.EnsureSuccessStatusCode();
@ -62,6 +68,39 @@ namespace DysonNetwork.Common.Clients
return file;
}
public async Task<CloudFile> ProcessImageAsync(Stream imageStream, string fileName, string? contentType = null)
{
using var content = new MultipartFormDataContent();
var fileContent = new StreamContent(imageStream);
if (!string.IsNullOrEmpty(contentType))
{
fileContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentType);
}
content.Add(fileContent, "image", fileName);
var response = await _httpClient.PostAsync("api/files/process-image", content);
response.EnsureSuccessStatusCode();
await using var responseStream = await response.Content.ReadAsStreamAsync();
var file = await JsonSerializer.DeserializeAsync<CloudFile>(responseStream, _jsonOptions);
return file;
}
public async Task<string> GetFileUrl(string fileId, bool useCdn = false)
{
var url = $"api/files/{fileId}/url";
if (useCdn)
{
url += "?useCdn=true";
}
var response = await _httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
return result.Trim('"');
}
public async Task DeleteFileAsync(string fileId)
{
var response = await _httpClient.DeleteAsync($"api/files/{fileId}");

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
@ -9,7 +9,13 @@
<ItemGroup>
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
<PackageReference Include="EFCore.NamingConventions" Version="9.0.0" />
<PackageReference Include="Microsoft.AspNetCore" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="2.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="7.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.6" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="7.0.0" />
<PackageReference Include="NetTopologySuite" Version="2.5.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NodaTime" Version="3.2.2" />

View File

@ -7,6 +7,15 @@ using OtpNet;
namespace DysonNetwork.Common.Models;
public enum AccountStatus
{
PendingActivation,
Active,
Suspended,
Banned,
Deleted
}
[Index(nameof(Name), IsUnique = true)]
public class Account : ModelBase
{
@ -30,6 +39,47 @@ public class Account : ModelBase
[JsonIgnore] public ICollection<Relationship> IncomingRelationships { get; set; } = new List<Relationship>();
[JsonIgnore] public ICollection<Subscription> Subscriptions { get; set; } = new List<Subscription>();
public AccountStatus Status { get; set; } = AccountStatus.PendingActivation;
[NotMapped]
public string? Email => GetPrimaryEmail();
public string? GetPrimaryEmail()
{
return Contacts
.FirstOrDefault(c => c.Type == AccountContactType.Email && c.IsPrimary)
?.Content;
}
public void SetPrimaryEmail(string email)
{
// Remove primary flag from existing primary email if any
foreach (var contact in Contacts.Where(c => c.Type == AccountContactType.Email && c.IsPrimary))
{
contact.IsPrimary = false;
}
// Find or create the email contact
var emailContact = Contacts.FirstOrDefault(c =>
c.Type == AccountContactType.Email &&
string.Equals(c.Content, email, StringComparison.OrdinalIgnoreCase));
if (emailContact == null)
{
emailContact = new AccountContact
{
Type = AccountContactType.Email,
Content = email,
IsPrimary = true
};
Contacts.Add(emailContact);
}
else
{
emailContact.IsPrimary = true;
}
}
}
public abstract class Leveling
@ -128,12 +178,29 @@ public class AccountAuthFactor : ModelBase
/// </summary>
public int Trustworthy { get; set; } = 1;
[MaxLength(100)]
public string Name { get; set; } = string.Empty;
[MaxLength(500)]
public string? Description { get; set; }
public bool IsDefault { get; set; }
public bool IsBackup { get; set; }
public Instant? LastUsedAt { get; set; }
public Instant? EnabledAt { get; set; }
public Instant? ExpiredAt { get; set; }
public Instant? DisabledAt { get; set; }
[Column(TypeName = "jsonb")]
public Dictionary<string, object>? Metadata { get; set; }
public Guid AccountId { get; set; }
[JsonIgnore] public Account Account { get; set; } = null!;
// Navigation property for related AuthSessions
[JsonIgnore]
public virtual ICollection<AuthSession>? Sessions { get; set; }
public AccountAuthFactor HashSecret(int cost = 12)
{
if (Secret == null) return this;
@ -174,20 +241,5 @@ public enum AccountAuthFactorType
EmailCode,
InAppCode,
TimedCode,
PinCode,
}
public class AccountConnection : ModelBase
{
public Guid Id { get; set; } = Guid.NewGuid();
[MaxLength(4096)] public string Provider { get; set; } = null!;
[MaxLength(8192)] public string ProvidedIdentifier { get; set; } = null!;
[Column(TypeName = "jsonb")] public Dictionary<string, object>? Meta { get; set; } = new();
[JsonIgnore] [MaxLength(4096)] public string? AccessToken { get; set; }
[JsonIgnore] [MaxLength(4096)] public string? RefreshToken { get; set; }
public Instant? LastUsedAt { get; set; }
public Guid AccountId { get; set; }
public Account Account { get; set; } = null!;
PinCode
}

View File

@ -1,6 +1,8 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json;
using System.Text.Json.Serialization;
using NodaTime;
namespace DysonNetwork.Common.Models;
@ -8,15 +10,8 @@ namespace DysonNetwork.Common.Models;
/// <summary>
/// Represents a connection between an account and an authentication provider
/// </summary>
public class AccountConnection
public class AccountConnection : ModelBase
{
/// <summary>
/// Unique identifier for the connection
/// </summary>
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string Id { get; set; } = null!;
/// <summary>
/// The account ID this connection is associated with
/// </summary>
@ -36,6 +31,16 @@ public class AccountConnection
[MaxLength(256)]
public string ProvidedIdentifier { get; set; } = null!;
/// <summary>
/// Alias for ProvidedIdentifier for backward compatibility
/// </summary>
[NotMapped]
public string ProviderId
{
get => ProvidedIdentifier;
set => ProvidedIdentifier = value;
}
/// <summary>
/// Display name for the connection
/// </summary>
@ -57,6 +62,27 @@ public class AccountConnection
/// </summary>
public Instant? ExpiresAt { get; set; }
/// <summary>
/// Raw profile data from the provider
/// </summary>
[Column(TypeName = "jsonb")]
public JsonDocument? ProfileData { get; set; }
/// <summary>
/// When the connection was first established
/// </summary>
public Instant ConnectedAt { get; set; } = SystemClock.Instance.GetCurrentInstant();
/// <summary>
/// Additional metadata about the connection
/// </summary>
[Column(TypeName = "jsonb")]
public JsonDocument? Metadata { get; set; }
/// <summary>
/// Gets a value indicating whether the connection is currently active
/// </summary>
[NotMapped]
/// <summary>
/// When the connection was first established
/// </summary>
@ -67,15 +93,33 @@ public class AccountConnection
/// </summary>
public Instant? LastUsedAt { get; set; }
/// <summary>
/// Additional metadata about the connection
/// </summary>
[Column(TypeName = "jsonb")]
public Dictionary<string, object>? Meta { get; set; }
/// <summary>
/// Navigation property for the associated account
/// </summary>
[ForeignKey(nameof(AccountId))]
[JsonIgnore]
public virtual Account? Account { get; set; }
/// <summary>
/// Updates the connection's tokens and related metadata
/// </summary>
/// <param name="accessToken">The new access token</param>
/// <param name="refreshToken">The new refresh token, if any</param>
/// <param name="expiresAt">When the access token expires, if any</param>
public void UpdateTokens(string? accessToken, string? refreshToken, Instant? expiresAt)
{
AccessToken = accessToken;
if (!string.IsNullOrEmpty(refreshToken))
{
RefreshToken = refreshToken;
}
if (expiresAt.HasValue)
{
ExpiresAt = expiresAt;
}
LastUsedAt = SystemClock.Instance.GetCurrentInstant();
}
}

View File

@ -0,0 +1,47 @@
namespace DysonNetwork.Common.Models.Auth;
/// <summary>
/// Represents the different types of authentication factors that can be used for multi-factor authentication.
/// </summary>
public enum AuthFactorType
{
/// <summary>
/// Password-based authentication factor.
/// </summary>
Password = 0,
/// <summary>
/// Time-based One-Time Password (TOTP) authentication factor.
/// </summary>
Totp = 1,
/// <summary>
/// Email-based authentication factor.
/// </summary>
Email = 2,
/// <summary>
/// Phone/SMS-based authentication factor.
/// </summary>
Phone = 3,
/// <summary>
/// Security key (FIDO2/WebAuthn) authentication factor.
/// </summary>
SecurityKey = 4,
/// <summary>
/// Recovery code authentication factor.
/// </summary>
RecoveryCode = 5,
/// <summary>
/// Backup code authentication factor.
/// </summary>
BackupCode = 6,
/// <summary>
/// OpenID Connect (OIDC) authentication factor.
/// </summary>
Oidc = 7
}

View File

@ -45,30 +45,3 @@ public enum AuthChallengePlatform
System = 100,
Unknown = 999
}
[JsonConverter(typeof(JsonStringEnumConverter))]
public enum AuthFactorType
{
Password = 0,
EmailCode = 1,
PhoneCode = 2,
Totp = 3,
WebAuthn = 4,
RecoveryCode = 5,
// Social and federation
Google = 10,
Apple = 11,
Microsoft = 12,
Facebook = 13,
Twitter = 14,
Github = 15,
// Enterprise
Saml = 50,
Oidc = 51,
Ldap = 52,
// Custom factor types
Custom = 100
}

View File

@ -1,10 +1,33 @@
using System.ComponentModel.DataAnnotations;
using NodaTime;
namespace DysonNetwork.Common.Models;
/// <summary>
/// Base class for all entity models in the system.
/// Provides common properties and functionality for tracking entity lifecycle.
/// </summary>
public abstract class ModelBase
{
public Instant CreatedAt { get; set; }
public Instant UpdatedAt { get; set; }
/// <summary>
/// Gets or sets the unique identifier for the entity.
/// </summary>
[Key]
public Guid Id { get; set; } = Guid.NewGuid();
/// <summary>
/// Gets or sets the date and time when the entity was created, in UTC.
/// </summary>
public Instant CreatedAt { get; set; } = SystemClock.Instance.GetCurrentInstant();
/// <summary>
/// Gets or sets the date and time when the entity was last updated, in UTC.
/// </summary>
public Instant UpdatedAt { get; set; } = SystemClock.Instance.GetCurrentInstant();
/// <summary>
/// Gets or sets the date and time when the entity was soft-deleted, in UTC.
/// Null if the entity has not been deleted.
/// </summary>
public Instant? DeletedAt { get; set; }
}

View File

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text.Json.Nodes;
namespace DysonNetwork.Common.Models;

View File

@ -0,0 +1,100 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;
using System.Threading.Tasks;
using DysonNetwork.Common.Extensions;
using Microsoft.AspNetCore.Http.Extensions;
namespace DysonNetwork.Common.Services.Permission;
[AttributeUsage(AttributeTargets.Method, Inherited = true)]
public class RequiredPermissionAttribute(string area, string key) : Attribute
{
public string Area { get; set; } = area;
public string Key { get; } = key;
}
public class PermissionMiddleware<TDbContext> where TDbContext : DbContext
{
private readonly RequestDelegate _next;
private readonly IServiceProvider _serviceProvider;
public PermissionMiddleware(RequestDelegate next, IServiceProvider serviceProvider)
{
_next = next;
_serviceProvider = serviceProvider;
}
public async Task InvokeAsync(HttpContext httpContext)
{
using var scope = _serviceProvider.CreateScope();
var permissionService = new PermissionService<TDbContext>(
scope.ServiceProvider.GetRequiredService<TDbContext>(),
scope.ServiceProvider.GetRequiredService<ICacheService>()
);
var endpoint = httpContext.GetEndpoint();
var attr = endpoint?.Metadata.OfType<RequiredPermissionAttribute>().FirstOrDefault();
if (attr != null)
{
if (httpContext.User.Identity?.IsAuthenticated != true)
{
httpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
await httpContext.Response.WriteAsync("Unauthorized");
return;
}
var currentUserId = httpContext.User.GetUserId();
if (currentUserId == Guid.Empty)
{
httpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
await httpContext.Response.WriteAsync("Unauthorized");
return;
}
// TODO: Check for superuser from PassClient
// if (currentUser.IsSuperuser)
// {
// await _next(httpContext);
// return;
// }
var actor = $"user:{currentUserId}";
var hasPermission = await permissionService.HasPermissionAsync(actor, attr.Area, attr.Key);
if (!hasPermission)
{
httpContext.Response.StatusCode = StatusCodes.Status403Forbidden;
await httpContext.Response.WriteAsync("Forbidden");
return;
}
}
await _next.Invoke(httpContext);
}
}
public static class PermissionServiceExtensions
{
public static IServiceCollection AddPermissionService<TDbContext>(this IServiceCollection services)
where TDbContext : DbContext
{
services.AddScoped<PermissionService<TDbContext>>(sp =>
new PermissionService<TDbContext>(
sp.GetRequiredService<TDbContext>(),
sp.GetRequiredService<ICacheService>()
));
return services;
}
public static IApplicationBuilder UsePermissionMiddleware<TDbContext>(this IApplicationBuilder builder)
where TDbContext : DbContext
{
return builder.UseMiddleware<PermissionMiddleware<TDbContext>>(builder.ApplicationServices);
}
}

View File

@ -0,0 +1,203 @@
using Microsoft.EntityFrameworkCore;
using NodaTime;
using System.Text.Json;
using DysonNetwork.Common.Models;
using DysonNetwork.Common.Services;
namespace DysonNetwork.Common.Services.Permission;
public class PermissionService<TDbContext> where TDbContext : DbContext
{
private readonly TDbContext _db;
private readonly ICacheService _cache;
private static readonly TimeSpan CacheExpiration = TimeSpan.FromMinutes(1);
private const string PermCacheKeyPrefix = "perm:";
private const string PermGroupCacheKeyPrefix = "perm-cg:";
private const string PermissionGroupPrefix = "perm-g:";
public PermissionService(TDbContext db, ICacheService cache)
{
_db = db;
_cache = cache;
}
private static string GetPermissionCacheKey(string actor, string area, string key) =>
PermCacheKeyPrefix + actor + ":" + area + ":" + key;
private static string GetGroupsCacheKey(string actor) =>
PermGroupCacheKeyPrefix + actor;
private static string GetPermissionGroupKey(string actor) =>
PermissionGroupPrefix + actor;
public async Task<bool> HasPermissionAsync(string actor, string area, string key)
{
var value = await GetPermissionAsync<bool>(actor, area, key);
return value;
}
public async Task<T?> GetPermissionAsync<T>(string actor, string area, string key)
{
var cacheKey = GetPermissionCacheKey(actor, area, key);
var (hit, cachedValue) = await _cache.GetAsyncWithStatus<T>(cacheKey);
if (hit)
return cachedValue;
var now = SystemClock.Instance.GetCurrentInstant();
var groupsKey = GetGroupsCacheKey(actor);
var groupsId = await _cache.GetAsync<List<Guid>>(groupsKey);
if (groupsId == null)
{
groupsId = await _db.Set<PermissionGroupMember>()
.Where(n => n.Actor == actor)
.Where(n => n.ExpiredAt == null || n.ExpiredAt > now)
.Where(n => n.AffectedAt == null || n.AffectedAt <= now)
.Select(e => e.GroupId)
.ToListAsync();
await _cache.SetWithGroupsAsync(groupsKey, groupsId,
[GetPermissionGroupKey(actor)],
CacheExpiration);
}
var permission = await _db.Set<PermissionNode>()
.Where(n => (n.GroupId == null && n.Actor == actor) ||
(n.GroupId != null && groupsId.Contains(n.GroupId.Value)))
.Where(n => n.Key == key && n.Area == area)
.Where(n => n.ExpiredAt == null || n.ExpiredAt > now)
.Where(n => n.AffectedAt == null || n.AffectedAt <= now)
.FirstOrDefaultAsync();
var result = permission is not null ? DeserializePermissionValue<T>(permission.Value) : default;
await _cache.SetWithGroupsAsync(cacheKey, result,
[GetPermissionGroupKey(actor)],
CacheExpiration);
return result;
}
public async Task<PermissionNode> AddPermissionNode<T>(
string actor,
string area,
string key,
T value,
Instant? expiredAt = null,
Instant? affectedAt = null
)
{
if (value is null) throw new ArgumentNullException(nameof(value));
var node = new PermissionNode
{
Actor = actor,
Key = key,
Area = area,
Value = SerializePermissionValue(value),
ExpiredAt = expiredAt,
AffectedAt = affectedAt
};
_db.Set<PermissionNode>().Add(node);
await _db.SaveChangesAsync();
// Invalidate related caches
await InvalidatePermissionCacheAsync(actor, area, key);
return node;
}
public async Task<PermissionNode> AddPermissionNodeToGroup<T>(
PermissionGroup group,
string actor,
string area,
string key,
T value,
Instant? expiredAt = null,
Instant? affectedAt = null
)
{
if (value is null) throw new ArgumentNullException(nameof(value));
var node = new PermissionNode
{
Actor = actor,
Key = key,
Area = area,
Value = SerializePermissionValue(value),
ExpiredAt = expiredAt,
AffectedAt = affectedAt,
Group = group,
GroupId = group.Id
};
_db.Set<PermissionNode>().Add(node);
await _db.SaveChangesAsync();
// Invalidate related caches
await InvalidatePermissionCacheAsync(actor, area, key);
await _cache.RemoveAsync(GetGroupsCacheKey(actor));
await _cache.RemoveGroupAsync(GetPermissionGroupKey(actor));
return node;
}
public async Task RemovePermissionNode(string actor, string area, string key)
{
var node = await _db.Set<PermissionNode>()
.Where(n => n.Actor == actor && n.Area == area && n.Key == key)
.FirstOrDefaultAsync();
if (node is not null) _db.Set<PermissionNode>().Remove(node);
await _db.SaveChangesAsync();
// Invalidate cache
await InvalidatePermissionCacheAsync(actor, area, key);
}
public async Task RemovePermissionNodeFromGroup(PermissionGroup group, string actor, string area, string key)
{
var node = await _db.Set<PermissionNode>()
.Where(n => n.GroupId == group.Id)
.Where(n => n.Actor == actor && n.Area == area && n.Key == key)
.FirstOrDefaultAsync();
if (node is null) return;
_db.Set<PermissionNode>().Remove(node);
await _db.SaveChangesAsync();
// Invalidate caches
await InvalidatePermissionCacheAsync(actor, area, key);
await _cache.RemoveAsync(GetGroupsCacheKey(actor));
await _cache.RemoveGroupAsync(GetPermissionGroupKey(actor));
}
private async Task InvalidatePermissionCacheAsync(string actor, string area, string key)
{
var cacheKey = GetPermissionCacheKey(actor, area, key);
await _cache.RemoveAsync(cacheKey);
}
private static T? DeserializePermissionValue<T>(JsonDocument json)
{
return JsonSerializer.Deserialize<T>(json.RootElement.GetRawText());
}
private static JsonDocument SerializePermissionValue<T>(T obj)
{
var str = JsonSerializer.Serialize(obj);
return JsonDocument.Parse(str);
}
public static PermissionNode NewPermissionNode<T>(string actor, string area, string key, T value)
{
return new PermissionNode
{
Actor = actor,
Area = area,
Key = key,
Value = SerializePermissionValue(value),
};
}
}

View File

@ -2,14 +2,14 @@ using System.Linq.Expressions;
using System.Reflection;
using DysonNetwork.Common.Models;
using DysonNetwork.Pass.Features.Auth.Models;
using DysonNetwork.Sphere.Permission;
// Permission types are now in DysonNetwork.Common.Models
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using NodaTime;
using Quartz;
using Account = DysonNetwork.Pass.Features.Auth.Models.Account;
using AccountConnection = DysonNetwork.Pass.Features.Auth.Models.AccountConnection;
using AccountAuthFactor = DysonNetwork.Pass.Features.Auth.Models.AccountAuthFactor;
using Account = DysonNetwork.Common.Models.Account;
using AccountConnection = DysonNetwork.Common.Models.AccountConnection;
using AccountAuthFactor = DysonNetwork.Common.Models.AccountAuthFactor;
using AuthSession = DysonNetwork.Pass.Features.Auth.Models.AuthSession;
using AuthChallenge = DysonNetwork.Pass.Features.Auth.Models.AuthChallenge;

View File

@ -44,7 +44,6 @@
<ItemGroup>
<ProjectReference Include="..\DysonNetwork.Common\DysonNetwork.Common.csproj" />
<ProjectReference Include="..\DysonNetwork.Sphere\DysonNetwork.Sphere.csproj" />
</ItemGroup>
</Project>

View File

@ -212,7 +212,7 @@ public class AccountCurrentController(
}
[HttpPost("statuses")]
[DysonNetwork.Sphere.Permission.RequiredPermission("global", "accounts.statuses.create")]
[DysonNetwork.Common.Services.Permission.RequiredPermission("global", "accounts.statuses.create")]
public async Task<ActionResult<Status>> CreateStatus([FromBody] AccountController.StatusRequest request)
{
if (HttpContext.Items["CurrentUser"] is not Common.Models.Account currentUser) return Unauthorized();

View File

@ -140,7 +140,7 @@ public class NotificationController(PassDatabase db, NotificationService nty) :
[HttpPost("send")]
[Authorize]
[DysonNetwork.Sphere.Permission.RequiredPermission("global", "notifications.send")]
[DysonNetwork.Common.Services.Permission.RequiredPermission("global", "notifications.send")]
public async Task<ActionResult> SendNotification(
[FromBody] NotificationWithAimRequest request,
[FromQuery] bool save = false

View File

@ -3,7 +3,7 @@ using DysonNetwork.Pass.Features.Auth;
using DysonNetwork.Pass.Features.Auth.OpenId;
using DysonNetwork.Pass.Email;
using DysonNetwork.Pass.Localization;
using DysonNetwork.Sphere.Permission;
// Permission types are now in DysonNetwork.Common.Models
using DysonNetwork.Pass.Storage;
using EFCore.BulkExtensions;
using Microsoft.EntityFrameworkCore;

View File

@ -3,7 +3,7 @@ using DysonNetwork.Pass.Storage;
using Microsoft.EntityFrameworkCore;
using NodaTime;
using DysonNetwork.Common.Models;
using DysonNetwork.Sphere.Permission;
// Permission types are now in DysonNetwork.Common.Models
namespace DysonNetwork.Pass.Features.Account;

View File

@ -6,7 +6,7 @@ namespace DysonNetwork.Pass.Features.Auth.Interfaces;
public interface IOidcService
{
string GetAuthorizationUrl(string state, string nonce);
Task<OidcUserInfo> ProcessCallbackAsync(OidcCallbackData callbackData);
Task<DysonNetwork.Common.Models.OidcUserInfo> ProcessCallbackAsync(OidcCallbackData callbackData);
Task<AuthResult> AuthenticateAsync(string provider, string code, string state);
IEnumerable<string> GetSupportedProviders();
}

View File

@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using DysonNetwork.Common.Models;
using NodaTime;
using AccountConnection = DysonNetwork.Common.Models.AccountConnection;
namespace DysonNetwork.Pass.Features.Auth.Models;

View File

@ -3,6 +3,7 @@ using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json;
using DysonNetwork.Common.Models;
using DysonNetwork.Common.Models.Auth;
using NodaTime;
namespace DysonNetwork.Pass.Features.Auth.Models;
@ -34,6 +35,9 @@ public class AccountAuthFactor : ModelBase
[Required]
public bool IsBackup { get; set; }
[Required]
public bool IsEnabled { get; set; } = true;
public Instant? LastUsedAt { get; set; }
public Instant? EnabledAt { get; set; }

View File

@ -1,70 +0,0 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json;
using System.Text.Json.Serialization;
using DysonNetwork.Pass.Models;
using NodaTime;
namespace DysonNetwork.Pass.Features.Auth.Models;
public class AccountConnection : ModelBase
{
[Required]
public Guid AccountId { get; set; }
[ForeignKey(nameof(AccountId))]
[JsonIgnore]
public virtual Account Account { get; set; } = null!;
[Required]
[MaxLength(50)]
public string Provider { get; set; } = string.Empty;
[Required]
[MaxLength(256)]
public string ProviderId { get; set; } = string.Empty;
[MaxLength(256)]
public string? DisplayName { get; set; }
[MaxLength(1000)]
public string? AccessToken { get; set; }
[MaxLength(1000)]
public string? RefreshToken { get; set; }
public Instant? ExpiresAt { get; set; }
[Column(TypeName = "jsonb")]
public JsonDocument? ProfileData { get; set; }
public Instant ConnectedAt { get; set; } = SystemClock.Instance.GetCurrentInstant();
public Instant? LastUsedAt { get; set; }
[Column(TypeName = "jsonb")]
public JsonDocument? Metadata { get; set; }
public bool IsConnected => ExpiresAt == null || ExpiresAt > SystemClock.Instance.GetCurrentInstant();
public void UpdateTokens(string? accessToken, string? refreshToken, Instant? expiresAt)
{
AccessToken = accessToken;
RefreshToken = refreshToken;
ExpiresAt = expiresAt;
LastUsedAt = SystemClock.Instance.GetCurrentInstant();
}
public void Disconnect()
{
AccessToken = null;
RefreshToken = null;
ExpiresAt = null;
ConnectedAt = default; // Set to default value for Instant
}
public void UpdateProfileData(JsonDocument? profileData)
{
ProfileData = profileData;
}
}

View File

@ -6,6 +6,8 @@ using DysonNetwork.Pass.Storage;
using NodaTime;
using DysonNetwork.Pass.Data;
using DysonNetwork.Common.Models;
using Account = DysonNetwork.Common.Models.Account;
using AccountConnection = DysonNetwork.Common.Models.AccountConnection;
namespace DysonNetwork.Pass.Features.Auth.OpenId;
@ -27,21 +29,24 @@ public class ConnectionController(
[HttpGet]
public async Task<ActionResult<List<AccountConnection>>> GetConnections()
{
if (HttpContext.Items["CurrentUser"] is not Models.Account currentUser)
if (HttpContext.Items["CurrentUser"] is not Account currentUser)
return Unauthorized();
var connections = await db.AccountConnections
.Where(c => c.AccountId == currentUser.Id)
.Select(c => new
.Select(c => new AccountConnection
{
c.Id,
c.AccountId,
c.Provider,
c.ProvidedIdentifier,
c.Meta,
c.LastUsedAt,
c.CreatedAt,
c.UpdatedAt,
Id = c.Id,
AccountId = c.AccountId,
Provider = c.Provider,
ProvidedIdentifier = c.ProvidedIdentifier,
DisplayName = c.DisplayName,
AccessToken = c.AccessToken,
RefreshToken = c.RefreshToken,
ExpiresAt = c.ExpiresAt,
LastUsedAt = c.LastUsedAt,
CreatedAt = c.CreatedAt,
UpdatedAt = c.UpdatedAt
})
.ToListAsync();
return Ok(connections);

View File

@ -1,8 +1,8 @@
using System.Net.Http.Json;
using System.Text.Json;
using DysonNetwork.Common.Models;
using DysonNetwork.Common.Services;
using DysonNetwork.Pass.Data;
using DysonNetwork.Sphere;
namespace DysonNetwork.Pass.Features.Auth.OpenId;
@ -47,7 +47,7 @@ public class DiscordOidcService(
})!;
}
public override async Task<OidcUserInfo> ProcessCallbackAsync(OidcCallbackData callbackData)
public override async Task<DysonNetwork.Common.Models.OidcUserInfo> ProcessCallbackAsync(OidcCallbackData callbackData)
{
var tokenResponse = await ExchangeCodeForTokensAsync(callbackData.Code);
if (tokenResponse?.AccessToken == null)
@ -84,7 +84,7 @@ public class DiscordOidcService(
return await response.Content.ReadFromJsonAsync<OidcTokenResponse>();
}
private async Task<OidcUserInfo> GetUserInfoAsync(string accessToken)
private async Task<DysonNetwork.Common.Models.OidcUserInfo> GetUserInfoAsync(string accessToken)
{
var client = HttpClientFactory.CreateClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://discord.com/users/@me");
@ -99,7 +99,7 @@ public class DiscordOidcService(
var userId = discordUser.GetProperty("id").GetString() ?? "";
var avatar = discordUser.TryGetProperty("avatar", out var avatarElement) ? avatarElement.GetString() : null;
return new OidcUserInfo
return new DysonNetwork.Common.Models.OidcUserInfo
{
UserId = userId,
Email = (discordUser.TryGetProperty("email", out var emailElement) ? emailElement.GetString() : null) ?? "",

View File

@ -1,6 +1,8 @@
using System.IdentityModel.Tokens.Jwt;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
using DysonNetwork.Common.Models;
using DysonNetwork.Common.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
@ -48,7 +50,7 @@ public abstract class OidcService(
/// <summary>
/// Process the callback from the OIDC provider
/// </summary>
public abstract Task<OidcUserInfo> ProcessCallbackAsync(OidcCallbackData callbackData);
public abstract Task<DysonNetwork.Common.Models.OidcUserInfo> ProcessCallbackAsync(OidcCallbackData callbackData);
/// <summary>
/// Gets the provider configuration
@ -145,7 +147,7 @@ public abstract class OidcService(
/// <summary>
/// Validates and extracts information from an ID token
/// </summary>
protected virtual OidcUserInfo ValidateAndExtractIdToken(string idToken,
protected virtual DysonNetwork.Common.Models.OidcUserInfo ValidateAndExtractIdToken(string idToken,
TokenValidationParameters validationParameters)
{
var handler = new JwtSecurityTokenHandler();
@ -171,18 +173,24 @@ public abstract class OidcService(
username = !string.IsNullOrEmpty(email) ? email.Split('@')[0] : null;
}
return new OidcUserInfo
// Convert the user info to our model
var userInfo = new DysonNetwork.Common.Models.OidcUserInfo
{
UserId = userId,
Email = email,
EmailVerified = emailVerified,
FirstName = givenName ?? "",
LastName = familyName ?? "",
DisplayName = name ?? $"{givenName} {familyName}".Trim(),
PreferredUsername = username ?? "",
ProfilePictureUrl = picture,
Provider = ProviderName
GivenName = givenName,
FamilyName = familyName,
Name = name,
UserId = userId,
Picture = picture,
AccessToken = "",
RefreshToken = "",
Provider = ProviderName,
ExpiresAt = null,
Claims = null
};
return userInfo;
}
/// <summary>
@ -190,7 +198,7 @@ public abstract class OidcService(
/// Also creates or updates the account connection
/// </summary>
public async Task<Challenge> CreateChallengeForUserAsync(
OidcUserInfo userInfo,
DysonNetwork.Common.Models.OidcUserInfo userInfo,
Models.Account account,
HttpContext request,
string deviceId
@ -205,14 +213,16 @@ public abstract class OidcService(
if (connection is null)
{
connection = new AccountConnection
connection = new DysonNetwork.Common.Models.AccountConnection
{
Provider = ProviderName,
ProvidedIdentifier = userInfo.UserId ?? "",
AccessToken = userInfo.AccessToken,
RefreshToken = userInfo.RefreshToken,
LastUsedAt = SystemClock.Instance.GetCurrentInstant(),
AccountId = account.Id
AccountId = account.Id,
CreatedAt = SystemClock.Instance.GetCurrentInstant(),
ProfileData = userInfo.Claims != null ? JsonSerializer.SerializeToDocument(userInfo.Claims) : null
};
await Db.AccountConnections.AddAsync(connection);
}

View File

@ -1,7 +1,7 @@
using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;
using DysonNetwork.Common.Models;
using DysonNetwork.Sphere.Permission;
using DysonNetwork.Common.Services.Permission;
using DysonNetwork.Sphere.Storage;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

View File

@ -4,7 +4,7 @@ using System.ComponentModel.DataAnnotations;
using DysonNetwork.Common.Interfaces;
using DysonNetwork.Common.Models;
using DysonNetwork.Sphere.Localization;
using DysonNetwork.Sphere.Permission;
using DysonNetwork.Common.Services.Permission;
using DysonNetwork.Sphere.Realm;
using DysonNetwork.Sphere.Storage;
using Microsoft.AspNetCore.Authorization;

View File

@ -1,4 +1,4 @@
using DysonNetwork.Sphere.Permission;
using DysonNetwork.Common.Services.Permission;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.RateLimiting;

View File

@ -1,182 +0,0 @@
using DysonNetwork.Common.Models;
using DysonNetwork.Sphere.Developer;
using DysonNetwork.Sphere.Storage;
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;
#nullable disable
namespace DysonNetwork.Sphere.Data.Migrations
{
/// <inheritdoc />
public partial class CustomAppsRefine : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "allow_offline_access",
table: "custom_apps");
migrationBuilder.DropColumn(
name: "allowed_grant_types",
table: "custom_apps");
migrationBuilder.DropColumn(
name: "allowed_scopes",
table: "custom_apps");
migrationBuilder.DropColumn(
name: "client_uri",
table: "custom_apps");
migrationBuilder.DropColumn(
name: "logo_uri",
table: "custom_apps");
migrationBuilder.DropColumn(
name: "post_logout_redirect_uris",
table: "custom_apps");
migrationBuilder.DropColumn(
name: "redirect_uris",
table: "custom_apps");
migrationBuilder.DropColumn(
name: "require_pkce",
table: "custom_apps");
migrationBuilder.DropColumn(
name: "verified_at",
table: "custom_apps");
migrationBuilder.RenameColumn(
name: "verified_as",
table: "custom_apps",
newName: "description");
migrationBuilder.AddColumn<CloudFileReferenceObject>(
name: "background",
table: "custom_apps",
type: "jsonb",
nullable: true);
migrationBuilder.AddColumn<CustomAppLinks>(
name: "links",
table: "custom_apps",
type: "jsonb",
nullable: true);
migrationBuilder.AddColumn<CustomAppOauthConfig>(
name: "oauth_config",
table: "custom_apps",
type: "jsonb",
nullable: true);
migrationBuilder.AddColumn<CloudFileReferenceObject>(
name: "picture",
table: "custom_apps",
type: "jsonb",
nullable: true);
migrationBuilder.AddColumn<VerificationMark>(
name: "verification",
table: "custom_apps",
type: "jsonb",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "background",
table: "custom_apps");
migrationBuilder.DropColumn(
name: "links",
table: "custom_apps");
migrationBuilder.DropColumn(
name: "oauth_config",
table: "custom_apps");
migrationBuilder.DropColumn(
name: "picture",
table: "custom_apps");
migrationBuilder.DropColumn(
name: "verification",
table: "custom_apps");
migrationBuilder.RenameColumn(
name: "description",
table: "custom_apps",
newName: "verified_as");
migrationBuilder.AddColumn<bool>(
name: "allow_offline_access",
table: "custom_apps",
type: "boolean",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<string>(
name: "allowed_grant_types",
table: "custom_apps",
type: "character varying(256)",
maxLength: 256,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<string>(
name: "allowed_scopes",
table: "custom_apps",
type: "character varying(256)",
maxLength: 256,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "client_uri",
table: "custom_apps",
type: "character varying(1024)",
maxLength: 1024,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "logo_uri",
table: "custom_apps",
type: "character varying(4096)",
maxLength: 4096,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "post_logout_redirect_uris",
table: "custom_apps",
type: "character varying(4096)",
maxLength: 4096,
nullable: true);
migrationBuilder.AddColumn<string>(
name: "redirect_uris",
table: "custom_apps",
type: "character varying(4096)",
maxLength: 4096,
nullable: false,
defaultValue: "");
migrationBuilder.AddColumn<bool>(
name: "require_pkce",
table: "custom_apps",
type: "boolean",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<Instant>(
name: "verified_at",
table: "custom_apps",
type: "timestamp with time zone",
nullable: true);
}
}
}

View File

@ -1,5 +1,5 @@
using DysonNetwork.Sphere.Permission;
using DysonNetwork.Common.Services.Permission;
using DysonNetwork.Sphere.Publisher;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

View File

@ -16,6 +16,9 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\DysonNetwork.Common\DysonNetwork.Common.csproj" />
<ProjectReference Include="..\DysonNetwork.Pass\DysonNetwork.Pass.csproj" />
<PackageReference Include="AngleSharp" Version="1.3.0" />
<PackageReference Include="BlurHashSharp.SkiaSharp" Version="1.3.4" />

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,61 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;
#nullable disable
namespace DysonNetwork.Sphere.Migrations
{
/// <inheritdoc />
public partial class EnrichAccountProfile : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<Instant>(
name: "birthday",
table: "account_profiles",
type: "timestamp with time zone",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "gender",
table: "account_profiles",
type: "character varying(1024)",
maxLength: 1024,
nullable: true);
migrationBuilder.AddColumn<Instant>(
name: "last_seen_at",
table: "account_profiles",
type: "timestamp with time zone",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "pronouns",
table: "account_profiles",
type: "character varying(1024)",
maxLength: 1024,
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "birthday",
table: "account_profiles");
migrationBuilder.DropColumn(
name: "gender",
table: "account_profiles");
migrationBuilder.DropColumn(
name: "last_seen_at",
table: "account_profiles");
migrationBuilder.DropColumn(
name: "pronouns",
table: "account_profiles");
}
}
}

View File

@ -1,52 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace DysonNetwork.Sphere.Migrations
{
/// <inheritdoc />
public partial class FixProfileRelationship : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "fk_account_profiles_accounts_id",
table: "account_profiles");
migrationBuilder.CreateIndex(
name: "ix_account_profiles_account_id",
table: "account_profiles",
column: "account_id",
unique: true);
migrationBuilder.AddForeignKey(
name: "fk_account_profiles_accounts_account_id",
table: "account_profiles",
column: "account_id",
principalTable: "accounts",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "fk_account_profiles_accounts_account_id",
table: "account_profiles");
migrationBuilder.DropIndex(
name: "ix_account_profiles_account_id",
table: "account_profiles");
migrationBuilder.AddForeignKey(
name: "fk_account_profiles_accounts_id",
table: "account_profiles",
column: "id",
principalTable: "accounts",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,89 +0,0 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;
#nullable disable
namespace DysonNetwork.Sphere.Migrations
{
/// <inheritdoc />
public partial class RefactorChatLastRead : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "chat_read_receipts");
migrationBuilder.AlterColumn<string>(
name: "type",
table: "chat_messages",
type: "character varying(1024)",
maxLength: 1024,
nullable: false,
oldClrType: typeof(string),
oldType: "text");
migrationBuilder.AddColumn<Instant>(
name: "last_read_at",
table: "chat_members",
type: "timestamp with time zone",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "last_read_at",
table: "chat_members");
migrationBuilder.AlterColumn<string>(
name: "type",
table: "chat_messages",
type: "text",
nullable: false,
oldClrType: typeof(string),
oldType: "character varying(1024)",
oldMaxLength: 1024);
migrationBuilder.CreateTable(
name: "chat_read_receipts",
columns: table => new
{
message_id = table.Column<Guid>(type: "uuid", nullable: false),
sender_id = table.Column<Guid>(type: "uuid", nullable: false),
created_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
deleted_at = table.Column<Instant>(type: "timestamp with time zone", nullable: true),
updated_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_chat_read_receipts", x => new { x.message_id, x.sender_id });
table.ForeignKey(
name: "fk_chat_read_receipts_chat_members_sender_id",
column: x => x.sender_id,
principalTable: "chat_members",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "fk_chat_read_receipts_chat_messages_message_id",
column: x => x.message_id,
principalTable: "chat_messages",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "ix_chat_read_receipts_message_id_sender_id",
table: "chat_read_receipts",
columns: new[] { "message_id", "sender_id" },
unique: true);
migrationBuilder.CreateIndex(
name: "ix_chat_read_receipts_sender_id",
table: "chat_read_receipts",
column: "sender_id");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,78 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace DysonNetwork.Sphere.Migrations
{
/// <inheritdoc />
public partial class UpdateRealtimeChat : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "ix_notification_push_subscriptions_device_id",
table: "notification_push_subscriptions");
migrationBuilder.DropIndex(
name: "ix_notification_push_subscriptions_device_token",
table: "notification_push_subscriptions");
migrationBuilder.RenameColumn(
name: "title",
table: "chat_realtime_call",
newName: "session_id");
migrationBuilder.AddColumn<string>(
name: "provider_name",
table: "chat_realtime_call",
type: "text",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "upstream",
table: "chat_realtime_call",
type: "jsonb",
nullable: true);
migrationBuilder.CreateIndex(
name: "ix_notification_push_subscriptions_device_token_device_id",
table: "notification_push_subscriptions",
columns: new[] { "device_token", "device_id" },
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "ix_notification_push_subscriptions_device_token_device_id",
table: "notification_push_subscriptions");
migrationBuilder.DropColumn(
name: "provider_name",
table: "chat_realtime_call");
migrationBuilder.DropColumn(
name: "upstream",
table: "chat_realtime_call");
migrationBuilder.RenameColumn(
name: "session_id",
table: "chat_realtime_call",
newName: "title");
migrationBuilder.CreateIndex(
name: "ix_notification_push_subscriptions_device_id",
table: "notification_push_subscriptions",
column: "device_id",
unique: true);
migrationBuilder.CreateIndex(
name: "ix_notification_push_subscriptions_device_token",
table: "notification_push_subscriptions",
column: "device_token",
unique: true);
}
}
}

View File

@ -1,34 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace DysonNetwork.Sphere.Migrations
{
/// <inheritdoc />
public partial class ModifyRelationshipStatusType : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<short>(
name: "status",
table: "account_relationships",
type: "smallint",
nullable: false,
oldClrType: typeof(int),
oldType: "integer");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<int>(
name: "status",
table: "account_relationships",
type: "integer",
nullable: false,
oldClrType: typeof(short),
oldType: "smallint");
}
}
}

View File

@ -1,22 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace DysonNetwork.Sphere.Migrations
{
/// <inheritdoc />
public partial class LimitedSizeForPictureIdOnPub : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,29 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace DysonNetwork.Sphere.Migrations
{
/// <inheritdoc />
public partial class AddCloudFileUsage : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "usage",
table: "files",
type: "character varying(1024)",
maxLength: 1024,
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "usage",
table: "files");
}
}
}

View File

@ -1,436 +0,0 @@
using System;
using System.Collections.Generic;
using DysonNetwork.Sphere.Storage;
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;
#nullable disable
namespace DysonNetwork.Sphere.Migrations
{
/// <inheritdoc />
public partial class RefactorCloudFileReference : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "fk_account_profiles_files_background_id",
table: "account_profiles");
migrationBuilder.DropForeignKey(
name: "fk_account_profiles_files_picture_id",
table: "account_profiles");
migrationBuilder.DropForeignKey(
name: "fk_chat_rooms_files_background_id",
table: "chat_rooms");
migrationBuilder.DropForeignKey(
name: "fk_chat_rooms_files_picture_id",
table: "chat_rooms");
migrationBuilder.DropForeignKey(
name: "fk_posts_posts_threaded_post_id",
table: "posts");
migrationBuilder.DropForeignKey(
name: "fk_publishers_files_background_id",
table: "publishers");
migrationBuilder.DropForeignKey(
name: "fk_publishers_files_picture_id",
table: "publishers");
migrationBuilder.DropForeignKey(
name: "fk_realms_files_background_id",
table: "realms");
migrationBuilder.DropForeignKey(
name: "fk_realms_files_picture_id",
table: "realms");
migrationBuilder.DropForeignKey(
name: "fk_stickers_files_image_id",
table: "stickers");
migrationBuilder.DropIndex(
name: "ix_stickers_image_id",
table: "stickers");
migrationBuilder.DropIndex(
name: "ix_realms_background_id",
table: "realms");
migrationBuilder.DropIndex(
name: "ix_realms_picture_id",
table: "realms");
migrationBuilder.DropIndex(
name: "ix_publishers_background_id",
table: "publishers");
migrationBuilder.DropIndex(
name: "ix_publishers_picture_id",
table: "publishers");
migrationBuilder.DropIndex(
name: "ix_posts_threaded_post_id",
table: "posts");
migrationBuilder.DropIndex(
name: "ix_chat_rooms_background_id",
table: "chat_rooms");
migrationBuilder.DropIndex(
name: "ix_chat_rooms_picture_id",
table: "chat_rooms");
migrationBuilder.DropIndex(
name: "ix_account_profiles_background_id",
table: "account_profiles");
migrationBuilder.DropIndex(
name: "ix_account_profiles_picture_id",
table: "account_profiles");
migrationBuilder.DropColumn(
name: "threaded_post_id",
table: "posts");
migrationBuilder.DropColumn(
name: "expired_at",
table: "files");
migrationBuilder.DropColumn(
name: "usage",
table: "files");
migrationBuilder.DropColumn(
name: "used_count",
table: "files");
migrationBuilder.AlterColumn<string>(
name: "image_id",
table: "stickers",
type: "character varying(32)",
maxLength: 32,
nullable: true,
oldClrType: typeof(string),
oldType: "character varying(32)",
oldMaxLength: 32);
migrationBuilder.AddColumn<CloudFileReferenceObject>(
name: "image",
table: "stickers",
type: "jsonb",
nullable: true,
defaultValueSql: "'[]'::jsonb"
);
migrationBuilder.AddColumn<CloudFileReferenceObject>(
name: "background",
table: "realms",
type: "jsonb",
nullable: true);
migrationBuilder.AddColumn<CloudFileReferenceObject>(
name: "picture",
table: "realms",
type: "jsonb",
nullable: true);
migrationBuilder.AddColumn<CloudFileReferenceObject>(
name: "background",
table: "publishers",
type: "jsonb",
nullable: true);
migrationBuilder.AddColumn<CloudFileReferenceObject>(
name: "picture",
table: "publishers",
type: "jsonb",
nullable: true);
migrationBuilder.AddColumn<List<CloudFileReferenceObject>>(
name: "attachments",
table: "posts",
type: "jsonb",
nullable: false,
defaultValueSql: "'[]'::jsonb"
);
migrationBuilder.AddColumn<CloudFileReferenceObject>(
name: "background",
table: "chat_rooms",
type: "jsonb",
nullable: true);
migrationBuilder.AddColumn<CloudFileReferenceObject>(
name: "picture",
table: "chat_rooms",
type: "jsonb",
nullable: true);
migrationBuilder.AddColumn<List<CloudFileReferenceObject>>(
name: "attachments",
table: "chat_messages",
type: "jsonb",
nullable: false,
defaultValueSql: "'[]'::jsonb"
);
migrationBuilder.AddColumn<CloudFileReferenceObject>(
name: "background",
table: "account_profiles",
type: "jsonb",
nullable: true);
migrationBuilder.AddColumn<CloudFileReferenceObject>(
name: "picture",
table: "account_profiles",
type: "jsonb",
nullable: true);
migrationBuilder.CreateTable(
name: "file_references",
columns: table => new
{
id = table.Column<Guid>(type: "uuid", nullable: false),
file_id = table.Column<string>(type: "character varying(32)", maxLength: 32, nullable: false),
usage = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: false),
resource_id = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: false),
expired_at = table.Column<Instant>(type: "timestamp with time zone", nullable: true),
created_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
updated_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
deleted_at = table.Column<Instant>(type: "timestamp with time zone", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("pk_file_references", x => x.id);
table.ForeignKey(
name: "fk_file_references_files_file_id",
column: x => x.file_id,
principalTable: "files",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "ix_file_references_file_id",
table: "file_references",
column: "file_id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "file_references");
migrationBuilder.DropColumn(
name: "image",
table: "stickers");
migrationBuilder.DropColumn(
name: "background",
table: "realms");
migrationBuilder.DropColumn(
name: "picture",
table: "realms");
migrationBuilder.DropColumn(
name: "background",
table: "publishers");
migrationBuilder.DropColumn(
name: "picture",
table: "publishers");
migrationBuilder.DropColumn(
name: "attachments",
table: "posts");
migrationBuilder.DropColumn(
name: "background",
table: "chat_rooms");
migrationBuilder.DropColumn(
name: "picture",
table: "chat_rooms");
migrationBuilder.DropColumn(
name: "attachments",
table: "chat_messages");
migrationBuilder.DropColumn(
name: "background",
table: "account_profiles");
migrationBuilder.DropColumn(
name: "picture",
table: "account_profiles");
migrationBuilder.AlterColumn<string>(
name: "image_id",
table: "stickers",
type: "character varying(32)",
maxLength: 32,
nullable: false,
defaultValue: "",
oldClrType: typeof(string),
oldType: "character varying(32)",
oldMaxLength: 32,
oldNullable: true);
migrationBuilder.AddColumn<Guid>(
name: "threaded_post_id",
table: "posts",
type: "uuid",
nullable: true);
migrationBuilder.AddColumn<Instant>(
name: "expired_at",
table: "files",
type: "timestamp with time zone",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "usage",
table: "files",
type: "character varying(1024)",
maxLength: 1024,
nullable: true);
migrationBuilder.AddColumn<int>(
name: "used_count",
table: "files",
type: "integer",
nullable: false,
defaultValue: 0);
migrationBuilder.CreateIndex(
name: "ix_stickers_image_id",
table: "stickers",
column: "image_id");
migrationBuilder.CreateIndex(
name: "ix_realms_background_id",
table: "realms",
column: "background_id");
migrationBuilder.CreateIndex(
name: "ix_realms_picture_id",
table: "realms",
column: "picture_id");
migrationBuilder.CreateIndex(
name: "ix_publishers_background_id",
table: "publishers",
column: "background_id");
migrationBuilder.CreateIndex(
name: "ix_publishers_picture_id",
table: "publishers",
column: "picture_id");
migrationBuilder.CreateIndex(
name: "ix_posts_threaded_post_id",
table: "posts",
column: "threaded_post_id",
unique: true);
migrationBuilder.CreateIndex(
name: "ix_chat_rooms_background_id",
table: "chat_rooms",
column: "background_id");
migrationBuilder.CreateIndex(
name: "ix_chat_rooms_picture_id",
table: "chat_rooms",
column: "picture_id");
migrationBuilder.CreateIndex(
name: "ix_account_profiles_background_id",
table: "account_profiles",
column: "background_id");
migrationBuilder.CreateIndex(
name: "ix_account_profiles_picture_id",
table: "account_profiles",
column: "picture_id");
migrationBuilder.AddForeignKey(
name: "fk_account_profiles_files_background_id",
table: "account_profiles",
column: "background_id",
principalTable: "files",
principalColumn: "id");
migrationBuilder.AddForeignKey(
name: "fk_account_profiles_files_picture_id",
table: "account_profiles",
column: "picture_id",
principalTable: "files",
principalColumn: "id");
migrationBuilder.AddForeignKey(
name: "fk_chat_rooms_files_background_id",
table: "chat_rooms",
column: "background_id",
principalTable: "files",
principalColumn: "id");
migrationBuilder.AddForeignKey(
name: "fk_chat_rooms_files_picture_id",
table: "chat_rooms",
column: "picture_id",
principalTable: "files",
principalColumn: "id");
migrationBuilder.AddForeignKey(
name: "fk_posts_posts_threaded_post_id",
table: "posts",
column: "threaded_post_id",
principalTable: "posts",
principalColumn: "id");
migrationBuilder.AddForeignKey(
name: "fk_publishers_files_background_id",
table: "publishers",
column: "background_id",
principalTable: "files",
principalColumn: "id");
migrationBuilder.AddForeignKey(
name: "fk_publishers_files_picture_id",
table: "publishers",
column: "picture_id",
principalTable: "files",
principalColumn: "id");
migrationBuilder.AddForeignKey(
name: "fk_realms_files_background_id",
table: "realms",
column: "background_id",
principalTable: "files",
principalColumn: "id");
migrationBuilder.AddForeignKey(
name: "fk_realms_files_picture_id",
table: "realms",
column: "picture_id",
principalTable: "files",
principalColumn: "id");
migrationBuilder.AddForeignKey(
name: "fk_stickers_files_image_id",
table: "stickers",
column: "image_id",
principalTable: "files",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
}
}
}

View File

@ -1,38 +0,0 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace DysonNetwork.Sphere.Migrations
{
/// <inheritdoc />
public partial class FixPushNotificationIndex : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "ix_notification_push_subscriptions_device_token_device_id",
table: "notification_push_subscriptions");
migrationBuilder.CreateIndex(
name: "ix_notification_push_subscriptions_device_token_device_id_acco",
table: "notification_push_subscriptions",
columns: new[] { "device_token", "device_id", "account_id" },
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropIndex(
name: "ix_notification_push_subscriptions_device_token_device_id_acco",
table: "notification_push_subscriptions");
migrationBuilder.CreateIndex(
name: "ix_notification_push_subscriptions_device_token_device_id",
table: "notification_push_subscriptions",
columns: new[] { "device_token", "device_id" },
unique: true);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,55 +0,0 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;
#nullable disable
namespace DysonNetwork.Sphere.Migrations
{
/// <inheritdoc />
public partial class RemoveActivities : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "activities");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "activities",
columns: table => new
{
id = table.Column<Guid>(type: "uuid", nullable: false),
account_id = table.Column<Guid>(type: "uuid", nullable: false),
created_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
deleted_at = table.Column<Instant>(type: "timestamp with time zone", nullable: true),
meta = table.Column<Dictionary<string, object>>(type: "jsonb", nullable: false),
resource_identifier = table.Column<string>(type: "character varying(4096)", maxLength: 4096, nullable: false),
type = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: false),
updated_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
users_visible = table.Column<ICollection<Guid>>(type: "jsonb", nullable: false),
visibility = table.Column<int>(type: "integer", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("pk_activities", x => x.id);
table.ForeignKey(
name: "fk_activities_accounts_account_id",
column: x => x.account_id,
principalTable: "accounts",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "ix_activities_account_id",
table: "activities",
column: "account_id");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,51 +0,0 @@
using DysonNetwork.Common.Models;
using DysonNetwork.Sphere.Chat;
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;
#nullable disable
namespace DysonNetwork.Sphere.Migrations
{
/// <inheritdoc />
public partial class EnrichChatMembers : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<Instant>(
name: "break_until",
table: "chat_members",
type: "timestamp with time zone",
nullable: true);
migrationBuilder.AddColumn<ChatTimeoutCause>(
name: "timeout_cause",
table: "chat_members",
type: "jsonb",
nullable: true);
migrationBuilder.AddColumn<Instant>(
name: "timeout_until",
table: "chat_members",
type: "timestamp with time zone",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "break_until",
table: "chat_members");
migrationBuilder.DropColumn(
name: "timeout_cause",
table: "chat_members");
migrationBuilder.DropColumn(
name: "timeout_until",
table: "chat_members");
}
}
}

View File

@ -1,91 +0,0 @@
using DysonNetwork.Common.Models;
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;
#nullable disable
namespace DysonNetwork.Sphere.Migrations
{
/// <inheritdoc />
public partial class ActiveBadgeAndVerification : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "verified_as",
table: "realms");
migrationBuilder.DropColumn(
name: "verified_at",
table: "realms");
migrationBuilder.AddColumn<VerificationMark>(
name: "verification",
table: "realms",
type: "jsonb",
nullable: true);
migrationBuilder.AddColumn<VerificationMark>(
name: "verification",
table: "publishers",
type: "jsonb",
nullable: true);
migrationBuilder.AddColumn<Instant>(
name: "activated_at",
table: "badges",
type: "timestamp with time zone",
nullable: true);
migrationBuilder.AddColumn<BadgeReferenceObject>(
name: "active_badge",
table: "account_profiles",
type: "jsonb",
nullable: true);
migrationBuilder.AddColumn<VerificationMark>(
name: "verification",
table: "account_profiles",
type: "jsonb",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "verification",
table: "realms");
migrationBuilder.DropColumn(
name: "verification",
table: "publishers");
migrationBuilder.DropColumn(
name: "activated_at",
table: "badges");
migrationBuilder.DropColumn(
name: "active_badge",
table: "account_profiles");
migrationBuilder.DropColumn(
name: "verification",
table: "account_profiles");
migrationBuilder.AddColumn<string>(
name: "verified_as",
table: "realms",
type: "character varying(4096)",
maxLength: 4096,
nullable: true);
migrationBuilder.AddColumn<Instant>(
name: "verified_at",
table: "realms",
type: "timestamp with time zone",
nullable: true);
}
}
}

View File

@ -1,144 +0,0 @@
using System;
using DysonNetwork.Common.Models;
using DysonNetwork.Sphere.Wallet;
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;
#nullable disable
namespace DysonNetwork.Sphere.Migrations
{
/// <inheritdoc />
public partial class BetterRecyclingFilesAndWalletSubscriptions : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "is_marked_recycle",
table: "files",
type: "boolean",
nullable: false,
defaultValue: false);
migrationBuilder.AddColumn<string>(
name: "location",
table: "account_profiles",
type: "character varying(1024)",
maxLength: 1024,
nullable: true);
migrationBuilder.AddColumn<SubscriptionReferenceObject>(
name: "stellar_membership",
table: "account_profiles",
type: "jsonb",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "time_zone",
table: "account_profiles",
type: "character varying(1024)",
maxLength: 1024,
nullable: true);
migrationBuilder.CreateTable(
name: "wallet_coupons",
columns: table => new
{
id = table.Column<Guid>(type: "uuid", nullable: false),
identifier = table.Column<string>(type: "character varying(4096)", maxLength: 4096, nullable: true),
code = table.Column<string>(type: "character varying(1024)", maxLength: 1024, nullable: true),
affected_at = table.Column<Instant>(type: "timestamp with time zone", nullable: true),
expired_at = table.Column<Instant>(type: "timestamp with time zone", nullable: true),
discount_amount = table.Column<decimal>(type: "numeric", nullable: true),
discount_rate = table.Column<double>(type: "double precision", nullable: true),
max_usage = table.Column<int>(type: "integer", nullable: true),
created_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
updated_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
deleted_at = table.Column<Instant>(type: "timestamp with time zone", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("pk_wallet_coupons", x => x.id);
});
migrationBuilder.CreateTable(
name: "wallet_subscriptions",
columns: table => new
{
id = table.Column<Guid>(type: "uuid", nullable: false),
begun_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
ended_at = table.Column<Instant>(type: "timestamp with time zone", nullable: true),
identifier = table.Column<string>(type: "character varying(4096)", maxLength: 4096, nullable: false),
is_active = table.Column<bool>(type: "boolean", nullable: false),
is_free_trial = table.Column<bool>(type: "boolean", nullable: false),
status = table.Column<int>(type: "integer", nullable: false),
payment_method = table.Column<string>(type: "character varying(4096)", maxLength: 4096, nullable: false),
payment_details = table.Column<PaymentDetails>(type: "jsonb", nullable: false),
base_price = table.Column<decimal>(type: "numeric", nullable: false),
coupon_id = table.Column<Guid>(type: "uuid", nullable: true),
renewal_at = table.Column<Instant>(type: "timestamp with time zone", nullable: true),
account_id = table.Column<Guid>(type: "uuid", nullable: false),
created_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
updated_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
deleted_at = table.Column<Instant>(type: "timestamp with time zone", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("pk_wallet_subscriptions", x => x.id);
table.ForeignKey(
name: "fk_wallet_subscriptions_accounts_account_id",
column: x => x.account_id,
principalTable: "accounts",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "fk_wallet_subscriptions_wallet_coupons_coupon_id",
column: x => x.coupon_id,
principalTable: "wallet_coupons",
principalColumn: "id");
});
migrationBuilder.CreateIndex(
name: "ix_wallet_subscriptions_account_id",
table: "wallet_subscriptions",
column: "account_id");
migrationBuilder.CreateIndex(
name: "ix_wallet_subscriptions_coupon_id",
table: "wallet_subscriptions",
column: "coupon_id");
migrationBuilder.CreateIndex(
name: "ix_wallet_subscriptions_identifier",
table: "wallet_subscriptions",
column: "identifier");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "wallet_subscriptions");
migrationBuilder.DropTable(
name: "wallet_coupons");
migrationBuilder.DropColumn(
name: "is_marked_recycle",
table: "files");
migrationBuilder.DropColumn(
name: "location",
table: "account_profiles");
migrationBuilder.DropColumn(
name: "stellar_membership",
table: "account_profiles");
migrationBuilder.DropColumn(
name: "time_zone",
table: "account_profiles");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,82 +0,0 @@
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace DysonNetwork.Sphere.Migrations
{
/// <inheritdoc />
public partial class WalletOrderAppDX : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "fk_payment_orders_wallets_payee_wallet_id",
table: "payment_orders");
migrationBuilder.AlterColumn<Guid>(
name: "payee_wallet_id",
table: "payment_orders",
type: "uuid",
nullable: true,
oldClrType: typeof(Guid),
oldType: "uuid");
migrationBuilder.AddColumn<string>(
name: "app_identifier",
table: "payment_orders",
type: "character varying(4096)",
maxLength: 4096,
nullable: true);
migrationBuilder.AddColumn<Dictionary<string, object>>(
name: "meta",
table: "payment_orders",
type: "jsonb",
nullable: true);
migrationBuilder.AddForeignKey(
name: "fk_payment_orders_wallets_payee_wallet_id",
table: "payment_orders",
column: "payee_wallet_id",
principalTable: "wallets",
principalColumn: "id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "fk_payment_orders_wallets_payee_wallet_id",
table: "payment_orders");
migrationBuilder.DropColumn(
name: "app_identifier",
table: "payment_orders");
migrationBuilder.DropColumn(
name: "meta",
table: "payment_orders");
migrationBuilder.AlterColumn<Guid>(
name: "payee_wallet_id",
table: "payment_orders",
type: "uuid",
nullable: false,
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
oldClrType: typeof(Guid),
oldType: "uuid",
oldNullable: true);
migrationBuilder.AddForeignKey(
name: "fk_payment_orders_wallets_payee_wallet_id",
table: "payment_orders",
column: "payee_wallet_id",
principalTable: "wallets",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,103 +0,0 @@
using System;
using System.Collections.Generic;
using DysonNetwork.Sphere.Connection.WebReader;
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;
#nullable disable
namespace DysonNetwork.Sphere.Migrations
{
/// <inheritdoc />
public partial class AddWebArticles : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "web_feeds",
columns: table => new
{
id = table.Column<Guid>(type: "uuid", nullable: false),
url = table.Column<string>(type: "character varying(8192)", maxLength: 8192, nullable: false),
title = table.Column<string>(type: "character varying(4096)", maxLength: 4096, nullable: false),
description = table.Column<string>(type: "character varying(8192)", maxLength: 8192, nullable: true),
preview = table.Column<LinkEmbed>(type: "jsonb", nullable: true),
publisher_id = table.Column<Guid>(type: "uuid", nullable: false),
created_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
updated_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
deleted_at = table.Column<Instant>(type: "timestamp with time zone", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("pk_web_feeds", x => x.id);
table.ForeignKey(
name: "fk_web_feeds_publishers_publisher_id",
column: x => x.publisher_id,
principalTable: "publishers",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "web_articles",
columns: table => new
{
id = table.Column<Guid>(type: "uuid", nullable: false),
title = table.Column<string>(type: "character varying(4096)", maxLength: 4096, nullable: false),
url = table.Column<string>(type: "character varying(8192)", maxLength: 8192, nullable: false),
author = table.Column<string>(type: "character varying(4096)", maxLength: 4096, nullable: true),
meta = table.Column<Dictionary<string, object>>(type: "jsonb", nullable: true),
preview = table.Column<LinkEmbed>(type: "jsonb", nullable: true),
content = table.Column<string>(type: "text", nullable: true),
published_at = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
feed_id = table.Column<Guid>(type: "uuid", nullable: false),
created_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
updated_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
deleted_at = table.Column<Instant>(type: "timestamp with time zone", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("pk_web_articles", x => x.id);
table.ForeignKey(
name: "fk_web_articles_web_feeds_feed_id",
column: x => x.feed_id,
principalTable: "web_feeds",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "ix_web_articles_feed_id",
table: "web_articles",
column: "feed_id");
migrationBuilder.CreateIndex(
name: "ix_web_articles_url",
table: "web_articles",
column: "url",
unique: true);
migrationBuilder.CreateIndex(
name: "ix_web_feeds_publisher_id",
table: "web_feeds",
column: "publisher_id");
migrationBuilder.CreateIndex(
name: "ix_web_feeds_url",
table: "web_feeds",
column: "url",
unique: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "web_articles");
migrationBuilder.DropTable(
name: "web_feeds");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,84 +0,0 @@
using System;
using DysonNetwork.Sphere.Connection.WebReader;
using Microsoft.EntityFrameworkCore.Migrations;
using NodaTime;
#nullable disable
namespace DysonNetwork.Sphere.Migrations
{
/// <inheritdoc />
public partial class AddRealmTags : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<WebFeedConfig>(
name: "config",
table: "web_feeds",
type: "jsonb",
nullable: false);
migrationBuilder.CreateTable(
name: "tags",
columns: table => new
{
id = table.Column<Guid>(type: "uuid", nullable: false),
name = table.Column<string>(type: "character varying(64)", maxLength: 64, nullable: false),
created_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
updated_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
deleted_at = table.Column<Instant>(type: "timestamp with time zone", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("pk_tags", x => x.id);
});
migrationBuilder.CreateTable(
name: "realm_tags",
columns: table => new
{
realm_id = table.Column<Guid>(type: "uuid", nullable: false),
tag_id = table.Column<Guid>(type: "uuid", nullable: false),
created_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
updated_at = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
deleted_at = table.Column<Instant>(type: "timestamp with time zone", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("pk_realm_tags", x => new { x.realm_id, x.tag_id });
table.ForeignKey(
name: "fk_realm_tags_realms_realm_id",
column: x => x.realm_id,
principalTable: "realms",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "fk_realm_tags_tags_tag_id",
column: x => x.tag_id,
principalTable: "tags",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "ix_realm_tags_tag_id",
table: "realm_tags",
column: "tag_id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "realm_tags");
migrationBuilder.DropTable(
name: "tags");
migrationBuilder.DropColumn(
name: "config",
table: "web_feeds");
}
}
}

View File

@ -1,7 +1,7 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json;
using DysonNetwork.Common.Models;
using DysonNetwork.Sphere.Permission;
using DysonNetwork.Common.Services.Permission;
using DysonNetwork.Sphere.Publisher;
using DysonNetwork.Sphere.Storage;
using Microsoft.AspNetCore.Authorization;

View File

@ -1,7 +1,7 @@
using System.ComponentModel.DataAnnotations;
using DysonNetwork.Common.Interfaces;
using DysonNetwork.Common.Models;
using DysonNetwork.Sphere.Permission;
using DysonNetwork.Common.Services.Permission;
using DysonNetwork.Sphere.Realm;
using DysonNetwork.Sphere.Storage;
using Microsoft.AspNetCore.Authorization;

View File

@ -1,6 +1,6 @@
using System.ComponentModel.DataAnnotations;
using DysonNetwork.Sphere.Permission;
using DysonNetwork.Common.Services.Permission;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

View File

@ -1,5 +1,5 @@
using System.ComponentModel.DataAnnotations;
using DysonNetwork.Sphere.Permission;
using DysonNetwork.Common.Services.Permission;
using DysonNetwork.Sphere.Post;
using DysonNetwork.Sphere.Publisher;
using DysonNetwork.Sphere.Storage;

View File

@ -1,5 +1,5 @@
using System.ComponentModel.DataAnnotations;
using DysonNetwork.Sphere.Permission;
using DysonNetwork.Common.Services.Permission;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;