fix
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
namespace MyOffice.Core.Attributes;
|
||||
|
||||
using System;
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)]
|
||||
public class LinkAttribute : Attribute
|
||||
{
|
||||
public LinkAttribute(Type type)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)]
|
||||
public class LinkFromAttribute : Attribute
|
||||
{
|
||||
public LinkFromAttribute(Type type)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)]
|
||||
public class LinkToAttribute : Attribute
|
||||
{
|
||||
public LinkToAttribute(Type type)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = true, Inherited = true)]
|
||||
public class LinkWithAttribute : Attribute
|
||||
{
|
||||
public LinkWithAttribute(Type type)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,26 @@ public static class StringExtensions
|
||||
return str != null && str.Equals(value, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
public static string? SafeTrim(this string? str)
|
||||
{
|
||||
return str == null ? str : str!.Trim();
|
||||
}
|
||||
|
||||
public static string? MaxOf(this string? str, int maxLength)
|
||||
{
|
||||
if (str == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (str.Length < maxLength)
|
||||
{
|
||||
return str;
|
||||
}
|
||||
|
||||
return str.Substring(0, maxLength);
|
||||
}
|
||||
|
||||
public static bool AsBool(this string? str, bool defaultValue = false)
|
||||
{
|
||||
return true.ToString().Equals(str, StringComparison.OrdinalIgnoreCase) || defaultValue;
|
||||
@@ -31,21 +51,11 @@ public static class StringExtensions
|
||||
|
||||
public static Guid AsGuid(this string str)
|
||||
{
|
||||
/*str = str
|
||||
.Replace("_", "/")
|
||||
.Replace("-", "+");
|
||||
byte[] buffer = Convert.FromBase64String(str + "==");
|
||||
return new Guid(buffer);*/
|
||||
return Guid.Parse(str);
|
||||
}
|
||||
|
||||
public static Guid? AsGuidNull(this string str)
|
||||
{
|
||||
/*str = str
|
||||
.Replace("_", "/")
|
||||
.Replace("-", "+");
|
||||
byte[] buffer = Convert.FromBase64String(str + "==");
|
||||
return new Guid(buffer);*/
|
||||
if (Guid.TryParse(str, out var guid))
|
||||
{
|
||||
return guid;
|
||||
|
||||
@@ -14,6 +14,7 @@ public class Account
|
||||
public IEnumerable<AccountAccess>? AccessRights { get; set; }
|
||||
public IEnumerable<Motion>? Motions { get; set; }
|
||||
public IEnumerable<AccountAccountCategory>? Categories { get; set; }
|
||||
public IEnumerable<AccountAccessInvite>? Invites { get; set; }
|
||||
}
|
||||
|
||||
public class AccountDetailed
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
namespace MyOffice.Data.Models.Accounts;
|
||||
|
||||
using Core.Attributes;
|
||||
using Users;
|
||||
|
||||
public class AccountAccessInvite
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid UserId { get; set; }
|
||||
public User User { get; set; }
|
||||
public User? User { get; set; }
|
||||
public Guid AccountId { get; set; }
|
||||
public Account? Account { get; set; }
|
||||
public DateTime CreatedOn { get; set; }
|
||||
public DateTime? AcceptedOn { get; set; }
|
||||
public DateTime? RejectedOn { get; set; }
|
||||
|
||||
@@ -6,4 +6,8 @@
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\MyOffice.Core\MyOffice.Core.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
namespace MyOffice.Data.Repositories.Account;
|
||||
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Models.Accounts;
|
||||
using MyOffice.Data.Repositories;
|
||||
|
||||
@@ -24,4 +25,18 @@ public class AccountAccessInviteRepository : AppRepository<AccountAccessInvite>,
|
||||
{
|
||||
return UpdateBase(invite) > 0;
|
||||
}
|
||||
|
||||
public IEnumerable<AccountAccessInvite> GetActive(string email)
|
||||
{
|
||||
return _context
|
||||
.AccountAccessInvites
|
||||
.Include(x => x.Account)
|
||||
.Where(x => x.Email == email && !x.AcceptedOn.HasValue && !x.RejectedOn.HasValue);
|
||||
|
||||
}
|
||||
|
||||
public AccountAccessInvite? Get(Guid id)
|
||||
{
|
||||
return _context.AccountAccessInvites.FirstOrDefault(x => x.Id == id);
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,10 @@ using MyOffice.Data.Repositories;
|
||||
|
||||
public class AccountAccessRepository : AppRepository<AccountAccess>, IAccountAccessRepository
|
||||
{
|
||||
public bool Add(AccountAccess accountAccess)
|
||||
{
|
||||
return AddBase(accountAccess) > 0;
|
||||
}
|
||||
|
||||
public bool Update(AccountAccess accountAccess)
|
||||
{
|
||||
|
||||
@@ -90,7 +90,7 @@ public class AccountRepository : AppRepository<Account>, IAccountRepository
|
||||
public Account? Get(Guid userId, Guid id)
|
||||
{
|
||||
return _context.Accounts!
|
||||
.Include(x => x.Categories)!
|
||||
.Include(x => x.Categories!.Where(c => c.Category.UserId == userId))!
|
||||
.ThenInclude(x => x.Category)
|
||||
.Include(x => x.AccessRights)!
|
||||
.ThenInclude(x => x.User)
|
||||
|
||||
@@ -5,6 +5,8 @@ using Models.Accounts;
|
||||
public interface IAccountAccessInviteRepository
|
||||
{
|
||||
AccountAccessInvite? Get(Guid userId, string email);
|
||||
IEnumerable<AccountAccessInvite> GetActive(string email);
|
||||
AccountAccessInvite? Get(Guid id);
|
||||
bool Add(AccountAccessInvite invite);
|
||||
bool Update(AccountAccessInvite invite);
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using Models.Accounts;
|
||||
|
||||
public interface IAccountAccessRepository
|
||||
{
|
||||
bool Add(AccountAccess accountAccess);
|
||||
bool Update(AccountAccess accountAccess);
|
||||
bool Delete(AccountAccess accountAccess);
|
||||
}
|
||||
@@ -176,6 +176,11 @@ public class AppDbContext : DbContext
|
||||
.WithMany(x => x.AccountAccessInvites)
|
||||
.HasForeignKey(x => x.UserId);
|
||||
|
||||
modelBuilder.Entity<AccountAccessInvite>()
|
||||
.HasOne(x => x.Account)
|
||||
.WithMany(x => x.Invites)
|
||||
.HasForeignKey(x => x.AccountId);
|
||||
|
||||
modelBuilder.Entity<Motion>()
|
||||
.HasOne(x => x.Account)
|
||||
.WithMany(x => x.Motions)
|
||||
|
||||
+713
@@ -0,0 +1,713 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using MyOffice.DbContext;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace MyOffice.Migrations.Postgres.Migrations
|
||||
{
|
||||
[DbContext(typeof(AppDbContext))]
|
||||
[Migration("20230728181916_AccountAccessInvites2")]
|
||||
partial class AccountAccessInvites2
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("Npgsql:CollationDefinition:my_ci_collation", "en-u-ks-primary,en-u-ks-primary,icu,False")
|
||||
.HasAnnotation("ProductVersion", "7.0.0")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Account", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("CurrencyGlobalId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("OwnerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CurrencyGlobalId");
|
||||
|
||||
b.HasIndex("OwnerId");
|
||||
|
||||
b.ToTable("Accounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccess", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<Guid>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<bool>("IsAllowManage")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("IsAllowRead")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("IsAllowWrite")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid>("OwnerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("OwnerId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AccountAccesses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccessInvite", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime?>("AcceptedOn")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<bool>("IsAllowWrite")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<DateTime?>("RejectedOn")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AccountAccessInvites");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccountCategory", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<Guid>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("CategoryId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("CategoryId");
|
||||
|
||||
b.ToTable("AccountAccountCategories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountCategory", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AccountCategories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Motion", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<decimal>("AmountMinus")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("numeric(18,6)");
|
||||
|
||||
b.Property<decimal>("AmountPlus")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("numeric(18,6)");
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTime>("DateTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTime?>("DeletedOn")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("ItemId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<Guid?>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("ItemId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("Motions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("CurrencyGlobalId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int?>("CurrentRateId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<bool>("IsPrimary")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ShortName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CurrencyGlobalId");
|
||||
|
||||
b.HasIndex("CurrentRateId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("Currencies");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyGlobal", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("DefaultQuantity")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Symbol")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("CurrencyGlobals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<Guid>("CurrencyId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("DateTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<int>("Quantity")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<decimal>("Rate")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CurrencyId");
|
||||
|
||||
b.ToTable("CurrencyRates");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Items.Item", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<Guid>("CategoryId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("ItemGlobalId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CategoryId");
|
||||
|
||||
b.HasIndex("ItemGlobalId");
|
||||
|
||||
b.ToTable("Items");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemCategory", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<bool>("IsInternal")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("ItemCategories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemGlobal", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("ItemGlobals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Users.User", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("CurrencyId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.UseCollation("my_ci_collation");
|
||||
|
||||
b.Property<string>("FirstName")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("FullName")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<bool>("IsEmailConfirmed")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("LastName")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Phone")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.UseCollation("my_ci_collation");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CurrencyId");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Users.UserExternal", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.UseCollation("my_ci_collation");
|
||||
|
||||
b.Property<string>("ExternalId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Provider")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.UseCollation("my_ci_collation");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("UserClaims");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Account", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Currencies.CurrencyGlobal", "CurrencyGlobal")
|
||||
.WithMany("Accounts")
|
||||
.HasForeignKey("CurrencyGlobalId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("MyOffice.Data.Models.Users.User", "Owner")
|
||||
.WithMany("Accounts")
|
||||
.HasForeignKey("OwnerId");
|
||||
|
||||
b.Navigation("CurrencyGlobal");
|
||||
|
||||
b.Navigation("Owner");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccess", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account")
|
||||
.WithMany("AccessRights")
|
||||
.HasForeignKey("AccountId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("MyOffice.Data.Models.Users.User", "Owner")
|
||||
.WithMany("AccountAccessOwners")
|
||||
.HasForeignKey("OwnerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("MyOffice.Data.Models.Users.User", "User")
|
||||
.WithMany("AccountAccess")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Account");
|
||||
|
||||
b.Navigation("Owner");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccessInvite", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Users.User", "User")
|
||||
.WithMany("AccountAccessInvites")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccountCategory", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account")
|
||||
.WithMany("Categories")
|
||||
.HasForeignKey("AccountId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("MyOffice.Data.Models.Accounts.AccountCategory", "Category")
|
||||
.WithMany("Accounts")
|
||||
.HasForeignKey("CategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Account");
|
||||
|
||||
b.Navigation("Category");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountCategory", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Users.User", "User")
|
||||
.WithMany("AccountCategories")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Motion", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account")
|
||||
.WithMany("Motions")
|
||||
.HasForeignKey("AccountId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("MyOffice.Data.Models.Items.Item", "Item")
|
||||
.WithMany("Motions")
|
||||
.HasForeignKey("ItemId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("MyOffice.Data.Models.Users.User", null)
|
||||
.WithMany("AccountMotions")
|
||||
.HasForeignKey("UserId");
|
||||
|
||||
b.Navigation("Account");
|
||||
|
||||
b.Navigation("Item");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Currencies.CurrencyGlobal", "CurrencyGlobal")
|
||||
.WithMany("Currencies")
|
||||
.HasForeignKey("CurrencyGlobalId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("MyOffice.Data.Models.Currencies.CurrencyRate", "CurrentRate")
|
||||
.WithMany("Currencies")
|
||||
.HasForeignKey("CurrentRateId");
|
||||
|
||||
b.HasOne("MyOffice.Data.Models.Users.User", "User")
|
||||
.WithMany("Currencies")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("CurrencyGlobal");
|
||||
|
||||
b.Navigation("CurrentRate");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Currencies.Currency", "Currency")
|
||||
.WithMany("Rates")
|
||||
.HasForeignKey("CurrencyId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Currency");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Items.Item", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Items.ItemCategory", "Category")
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("CategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("MyOffice.Data.Models.Items.ItemGlobal", "ItemGlobal")
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("ItemGlobalId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Category");
|
||||
|
||||
b.Navigation("ItemGlobal");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemCategory", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Users.User", "User")
|
||||
.WithMany("ItemCategories")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Users.User", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Currencies.CurrencyGlobal", "Currency")
|
||||
.WithMany()
|
||||
.HasForeignKey("CurrencyId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Currency");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Users.UserExternal", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Users.User", "User")
|
||||
.WithMany("UserClaims")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Account", b =>
|
||||
{
|
||||
b.Navigation("AccessRights");
|
||||
|
||||
b.Navigation("Categories");
|
||||
|
||||
b.Navigation("Motions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountCategory", b =>
|
||||
{
|
||||
b.Navigation("Accounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b =>
|
||||
{
|
||||
b.Navigation("Rates");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyGlobal", b =>
|
||||
{
|
||||
b.Navigation("Accounts");
|
||||
|
||||
b.Navigation("Currencies");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b =>
|
||||
{
|
||||
b.Navigation("Currencies");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Items.Item", b =>
|
||||
{
|
||||
b.Navigation("Motions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemCategory", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemGlobal", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Users.User", b =>
|
||||
{
|
||||
b.Navigation("AccountAccess");
|
||||
|
||||
b.Navigation("AccountAccessInvites");
|
||||
|
||||
b.Navigation("AccountAccessOwners");
|
||||
|
||||
b.Navigation("AccountCategories");
|
||||
|
||||
b.Navigation("AccountMotions");
|
||||
|
||||
b.Navigation("Accounts");
|
||||
|
||||
b.Navigation("Currencies");
|
||||
|
||||
b.Navigation("ItemCategories");
|
||||
|
||||
b.Navigation("UserClaims");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace MyOffice.Migrations.Postgres.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AccountAccessInvites2 : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "UserId",
|
||||
table: "AccountAccessInvites",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AccountAccessInvites_UserId",
|
||||
table: "AccountAccessInvites",
|
||||
column: "UserId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_AccountAccessInvites_Users_UserId",
|
||||
table: "AccountAccessInvites",
|
||||
column: "UserId",
|
||||
principalTable: "Users",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_AccountAccessInvites_Users_UserId",
|
||||
table: "AccountAccessInvites");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_AccountAccessInvites_UserId",
|
||||
table: "AccountAccessInvites");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "UserId",
|
||||
table: "AccountAccessInvites");
|
||||
}
|
||||
}
|
||||
}
|
||||
+728
@@ -0,0 +1,728 @@
|
||||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using MyOffice.DbContext;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace MyOffice.Migrations.Postgres.Migrations
|
||||
{
|
||||
[DbContext(typeof(AppDbContext))]
|
||||
[Migration("20230728192017_AccountAccessInvites3")]
|
||||
partial class AccountAccessInvites3
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("Npgsql:CollationDefinition:my_ci_collation", "en-u-ks-primary,en-u-ks-primary,icu,False")
|
||||
.HasAnnotation("ProductVersion", "7.0.0")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Account", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("CurrencyGlobalId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid?>("OwnerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CurrencyGlobalId");
|
||||
|
||||
b.HasIndex("OwnerId");
|
||||
|
||||
b.ToTable("Accounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccess", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<Guid>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<bool>("IsAllowManage")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("IsAllowRead")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<bool>("IsAllowWrite")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid>("OwnerId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Type")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("OwnerId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AccountAccesses");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccessInvite", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime?>("AcceptedOn")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<bool>("IsAllowWrite")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<DateTime?>("RejectedOn")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AccountAccessInvites");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccountCategory", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<Guid>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("CategoryId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("CategoryId");
|
||||
|
||||
b.ToTable("AccountAccountCategories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountCategory", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AccountCategories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Motion", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<decimal>("AmountMinus")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("numeric(18,6)");
|
||||
|
||||
b.Property<decimal>("AmountPlus")
|
||||
.HasPrecision(18, 6)
|
||||
.HasColumnType("numeric(18,6)");
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTime>("DateTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTime?>("DeletedOn")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("ItemId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<Guid?>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("ItemId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("Motions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("CurrencyGlobalId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int?>("CurrentRateId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<bool>("IsPrimary")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("ShortName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CurrencyGlobalId");
|
||||
|
||||
b.HasIndex("CurrentRateId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("Currencies");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyGlobal", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("DefaultQuantity")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Symbol")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("CurrencyGlobals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<Guid>("CurrencyId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("DateTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<int>("Quantity")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<decimal>("Rate")
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CurrencyId");
|
||||
|
||||
b.ToTable("CurrencyRates");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Items.Item", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<Guid>("CategoryId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<Guid>("ItemGlobalId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CategoryId");
|
||||
|
||||
b.HasIndex("ItemGlobalId");
|
||||
|
||||
b.ToTable("Items");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemCategory", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<bool>("IsInternal")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("ItemCategories");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemGlobal", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("Name")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("ItemGlobals");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Users.User", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<string>("CurrencyId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.UseCollation("my_ci_collation");
|
||||
|
||||
b.Property<string>("FirstName")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("FullName")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<bool>("IsEmailConfirmed")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("LastName")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("PasswordHash")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Phone")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.UseCollation("my_ci_collation");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CurrencyId");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Users.UserExternal", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.UseCollation("my_ci_collation");
|
||||
|
||||
b.Property<string>("ExternalId")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("Provider")
|
||||
.IsRequired()
|
||||
.HasColumnType("text")
|
||||
.UseCollation("my_ci_collation");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("UserClaims");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Account", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Currencies.CurrencyGlobal", "CurrencyGlobal")
|
||||
.WithMany("Accounts")
|
||||
.HasForeignKey("CurrencyGlobalId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("MyOffice.Data.Models.Users.User", "Owner")
|
||||
.WithMany("Accounts")
|
||||
.HasForeignKey("OwnerId");
|
||||
|
||||
b.Navigation("CurrencyGlobal");
|
||||
|
||||
b.Navigation("Owner");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccess", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account")
|
||||
.WithMany("AccessRights")
|
||||
.HasForeignKey("AccountId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("MyOffice.Data.Models.Users.User", "Owner")
|
||||
.WithMany("AccountAccessOwners")
|
||||
.HasForeignKey("OwnerId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("MyOffice.Data.Models.Users.User", "User")
|
||||
.WithMany("AccountAccess")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Account");
|
||||
|
||||
b.Navigation("Owner");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccessInvite", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account")
|
||||
.WithMany("Invites")
|
||||
.HasForeignKey("AccountId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("MyOffice.Data.Models.Users.User", "User")
|
||||
.WithMany("AccountAccessInvites")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Account");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccountCategory", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account")
|
||||
.WithMany("Categories")
|
||||
.HasForeignKey("AccountId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("MyOffice.Data.Models.Accounts.AccountCategory", "Category")
|
||||
.WithMany("Accounts")
|
||||
.HasForeignKey("CategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Account");
|
||||
|
||||
b.Navigation("Category");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountCategory", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Users.User", "User")
|
||||
.WithMany("AccountCategories")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Motion", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account")
|
||||
.WithMany("Motions")
|
||||
.HasForeignKey("AccountId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("MyOffice.Data.Models.Items.Item", "Item")
|
||||
.WithMany("Motions")
|
||||
.HasForeignKey("ItemId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("MyOffice.Data.Models.Users.User", null)
|
||||
.WithMany("AccountMotions")
|
||||
.HasForeignKey("UserId");
|
||||
|
||||
b.Navigation("Account");
|
||||
|
||||
b.Navigation("Item");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Currencies.CurrencyGlobal", "CurrencyGlobal")
|
||||
.WithMany("Currencies")
|
||||
.HasForeignKey("CurrencyGlobalId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("MyOffice.Data.Models.Currencies.CurrencyRate", "CurrentRate")
|
||||
.WithMany("Currencies")
|
||||
.HasForeignKey("CurrentRateId");
|
||||
|
||||
b.HasOne("MyOffice.Data.Models.Users.User", "User")
|
||||
.WithMany("Currencies")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("CurrencyGlobal");
|
||||
|
||||
b.Navigation("CurrentRate");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Currencies.Currency", "Currency")
|
||||
.WithMany("Rates")
|
||||
.HasForeignKey("CurrencyId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Currency");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Items.Item", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Items.ItemCategory", "Category")
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("CategoryId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("MyOffice.Data.Models.Items.ItemGlobal", "ItemGlobal")
|
||||
.WithMany("Items")
|
||||
.HasForeignKey("ItemGlobalId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Category");
|
||||
|
||||
b.Navigation("ItemGlobal");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemCategory", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Users.User", "User")
|
||||
.WithMany("ItemCategories")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Users.User", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Currencies.CurrencyGlobal", "Currency")
|
||||
.WithMany()
|
||||
.HasForeignKey("CurrencyId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Currency");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Users.UserExternal", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Users.User", "User")
|
||||
.WithMany("UserClaims")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.Account", b =>
|
||||
{
|
||||
b.Navigation("AccessRights");
|
||||
|
||||
b.Navigation("Categories");
|
||||
|
||||
b.Navigation("Invites");
|
||||
|
||||
b.Navigation("Motions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountCategory", b =>
|
||||
{
|
||||
b.Navigation("Accounts");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Currencies.Currency", b =>
|
||||
{
|
||||
b.Navigation("Rates");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyGlobal", b =>
|
||||
{
|
||||
b.Navigation("Accounts");
|
||||
|
||||
b.Navigation("Currencies");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Currencies.CurrencyRate", b =>
|
||||
{
|
||||
b.Navigation("Currencies");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Items.Item", b =>
|
||||
{
|
||||
b.Navigation("Motions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemCategory", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Items.ItemGlobal", b =>
|
||||
{
|
||||
b.Navigation("Items");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Users.User", b =>
|
||||
{
|
||||
b.Navigation("AccountAccess");
|
||||
|
||||
b.Navigation("AccountAccessInvites");
|
||||
|
||||
b.Navigation("AccountAccessOwners");
|
||||
|
||||
b.Navigation("AccountCategories");
|
||||
|
||||
b.Navigation("AccountMotions");
|
||||
|
||||
b.Navigation("Accounts");
|
||||
|
||||
b.Navigation("Currencies");
|
||||
|
||||
b.Navigation("ItemCategories");
|
||||
|
||||
b.Navigation("UserClaims");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace MyOffice.Migrations.Postgres.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AccountAccessInvites3 : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "AccountId",
|
||||
table: "AccountAccessInvites",
|
||||
type: "uuid",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"));
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AccountAccessInvites_AccountId",
|
||||
table: "AccountAccessInvites",
|
||||
column: "AccountId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_AccountAccessInvites_Accounts_AccountId",
|
||||
table: "AccountAccessInvites",
|
||||
column: "AccountId",
|
||||
principalTable: "Accounts",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_AccountAccessInvites_Accounts_AccountId",
|
||||
table: "AccountAccessInvites");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_AccountAccessInvites_AccountId",
|
||||
table: "AccountAccessInvites");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "AccountId",
|
||||
table: "AccountAccessInvites");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -102,6 +102,9 @@ namespace MyOffice.Migrations.Postgres.Migrations
|
||||
b.Property<DateTime?>("AcceptedOn")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("AccountId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.Property<DateTime>("CreatedOn")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
@@ -115,8 +118,15 @@ namespace MyOffice.Migrations.Postgres.Migrations
|
||||
b.Property<DateTime?>("RejectedOn")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<Guid>("UserId")
|
||||
.HasColumnType("uuid");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AccountAccessInvites");
|
||||
});
|
||||
|
||||
@@ -481,6 +491,25 @@ namespace MyOffice.Migrations.Postgres.Migrations
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccessInvite", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account")
|
||||
.WithMany("Invites")
|
||||
.HasForeignKey("AccountId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("MyOffice.Data.Models.Users.User", "User")
|
||||
.WithMany("AccountAccessInvites")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Account");
|
||||
|
||||
b.Navigation("User");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("MyOffice.Data.Models.Accounts.AccountAccountCategory", b =>
|
||||
{
|
||||
b.HasOne("MyOffice.Data.Models.Accounts.Account", "Account")
|
||||
@@ -628,6 +657,8 @@ namespace MyOffice.Migrations.Postgres.Migrations
|
||||
|
||||
b.Navigation("Categories");
|
||||
|
||||
b.Navigation("Invites");
|
||||
|
||||
b.Navigation("Motions");
|
||||
});
|
||||
|
||||
@@ -672,6 +703,8 @@ namespace MyOffice.Migrations.Postgres.Migrations
|
||||
{
|
||||
b.Navigation("AccountAccess");
|
||||
|
||||
b.Navigation("AccountAccessInvites");
|
||||
|
||||
b.Navigation("AccountAccessOwners");
|
||||
|
||||
b.Navigation("AccountCategories");
|
||||
|
||||
@@ -18,6 +18,9 @@ export class ApiRoutes {
|
||||
static SettingsAccountAccesses = '/api/settings/accounts/:id/access';
|
||||
static SettingsAccountAccess = '/api/settings/accounts/:id/access/:access';
|
||||
static SettingsAccountAccountCategory = '/api/settings/accounts/:id/category/:categoryId';
|
||||
static SettingsAccountInvites = '/api/settings/accounts/invites';
|
||||
static SettingsAccountInviteAccept = '/api/settings/accounts/invites/:id/accept';
|
||||
static SettingsAccountInviteReject = '/api/settings/accounts/invites/:id/reject';
|
||||
|
||||
static SettingsItemCategories = '/api/settings/item-categories';
|
||||
static SettingsItemCategory = '/api/settings/item-categories/:id';
|
||||
|
||||
@@ -24,8 +24,12 @@ export class ErrorInterceptor implements HttpInterceptor {
|
||||
this.authenticationService.logout();
|
||||
location.reload();
|
||||
}
|
||||
console.log(err);
|
||||
const error = err.message || err.error.message || err.statusText;
|
||||
let error = err.message || err.statusText;
|
||||
error = !err.error ? error : err.error.message || err.error.title;
|
||||
|
||||
if (!error) {
|
||||
console.log('not parsed error', err);
|
||||
}
|
||||
return throwError(error);
|
||||
//return throwError(err.error || err);
|
||||
})
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
export interface AccountInviteModel {
|
||||
id?: string,
|
||||
account?: string,
|
||||
allowWrite: boolean,
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import { NgxCurrencyModule } from "ngx-currency";
|
||||
import { MatExpansionModule } from '@angular/material/expansion';
|
||||
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatMenuModule } from '@angular/material/menu';
|
||||
|
||||
// app
|
||||
import { PagesRoutingModule } from './pages-routing.module';
|
||||
@@ -88,6 +89,7 @@ import { SettingsItemCategoryEditComponent } from './settings/item/edit.item.cat
|
||||
NgxMaskModule,
|
||||
NgxCurrencyModule,
|
||||
MatCheckboxModule,
|
||||
MatMenuModule,
|
||||
],
|
||||
providers: [
|
||||
{ provide: MAT_DATE_LOCALE, useValue: 'en-GB' },
|
||||
|
||||
@@ -17,13 +17,19 @@
|
||||
</mat-card-subtitle>
|
||||
</mat-card-title-group>
|
||||
<div fxFlex></div>
|
||||
<div *ngIf="invites && invites.length > 0" class="m-r-10">
|
||||
<button mat-raised-button color="warn" [matMenuTriggerFor]="menu">Invites</button>
|
||||
<mat-menu #menu="matMenu">
|
||||
<button *ngFor="let invite of invites" mat-menu-item (click)="startInvite(invite)">{{invite.account}}</button>
|
||||
</mat-menu>
|
||||
</div>
|
||||
<button class="btn-space " (click)="add()" mat-raised-button color="primary">
|
||||
Add
|
||||
</button>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<div class="body table-responsive">
|
||||
<mat-tab-group mat-stretch-tabs="false" mat-align-tabs="start">
|
||||
<mat-tab-group mat-stretch-tabs="false" mat-align-tabs="start" [(selectedIndex)]="tabIndex">
|
||||
<mat-tab *ngFor="let category of accountCategories" label="{{category.name}}">
|
||||
<table class="table">
|
||||
<tbody>
|
||||
|
||||
@@ -10,6 +10,7 @@ import { MatDialog } from '@angular/material/dialog';
|
||||
import { ApiRoutes } from '../../../api-routes';
|
||||
import { AccountModel } from '../../../model/account.model';
|
||||
import { AccountCategoryModel } from '../../../model/account.category.model';
|
||||
import { AccountInviteModel } from '../../../model/account.invite.model';
|
||||
import { SettingsAccountAddComponent } from './add.account.component';
|
||||
import { SettingsAccountEditComponent } from './edit.account.component';
|
||||
import { SettingsAccountAccessComponent } from './access.account.component';
|
||||
@@ -22,6 +23,8 @@ import { AccountCategoryService } from '../../../services/account.category.servi
|
||||
export class SettingsAccountComponent {
|
||||
public accountCategories?: AccountCategoryModel[];
|
||||
public accounts?: AccountModel[];
|
||||
public invites?: AccountInviteModel[];
|
||||
public tabIndex = 0;
|
||||
|
||||
constructor(
|
||||
private httpClient: HttpClient,
|
||||
@@ -32,13 +35,35 @@ export class SettingsAccountComponent {
|
||||
|
||||
ngOnInit(): void {
|
||||
this.loadCategories();
|
||||
this.loadInvites();
|
||||
}
|
||||
|
||||
private loadAccounts() {
|
||||
private loadAccounts(accountToShow?: string) {
|
||||
this.httpClient
|
||||
.get<AccountModel[]>(ApiRoutes.SettingsAccounts)
|
||||
.subscribe(data => {
|
||||
this.accounts = data;
|
||||
if (accountToShow) {
|
||||
var idx = -1;
|
||||
var account = this.accounts.find(x => x.id === accountToShow);
|
||||
if (account && account.categories && account.categories.length > 0) {
|
||||
for (var i = 0; i < this.accountCategories!.length; i++) {
|
||||
if (account!.categories!.find(c => c.id === this.accountCategories![i].id)) {
|
||||
idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.tabIndex = idx === -1 ? this.accountCategories!.length : idx;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private loadInvites() {
|
||||
return this.httpClient
|
||||
.get<AccountInviteModel[]>(ApiRoutes.SettingsAccountInvites)
|
||||
.subscribe(response => {
|
||||
this.invites = response;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -118,6 +143,57 @@ export class SettingsAccountComponent {
|
||||
this.loadAccounts();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public startInvite(invite: AccountInviteModel) {
|
||||
Swal.fire({
|
||||
title: 'Accept to invite the account "' + invite.account + '"',
|
||||
input: 'text',
|
||||
inputLabel: 'Accept with name',
|
||||
inputValue: invite.account,
|
||||
showDenyButton: true,
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Accept',
|
||||
denyButtonText: 'Reject',
|
||||
showLoaderOnConfirm: true,
|
||||
preConfirm: (input) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.httpClient.post(ApiRoutes.SettingsAccountInviteAccept.replace(':id', invite.id!), { name: input })
|
||||
.subscribe(data => {
|
||||
resolve(data);
|
||||
}, error => {
|
||||
Swal.showValidationMessage(error);
|
||||
reject();
|
||||
});
|
||||
|
||||
}).catch(x => {
|
||||
return false;
|
||||
});
|
||||
},
|
||||
preDeny: (x) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.httpClient.post(ApiRoutes.SettingsAccountInviteReject.replace(':id', invite.id!), null)
|
||||
.subscribe(data => {
|
||||
resolve(data);
|
||||
}, error => {
|
||||
Swal.showValidationMessage(error.detail);
|
||||
reject();
|
||||
});
|
||||
|
||||
}).catch(x => {
|
||||
return false;
|
||||
});
|
||||
},
|
||||
allowOutsideClick: () => !Swal.isLoading(),
|
||||
}).then((result) => {
|
||||
var id;
|
||||
if (result.value) {
|
||||
var account = result.value as AccountModel;
|
||||
id = account.id;
|
||||
}
|
||||
this.loadInvites();
|
||||
this.loadAccounts(id);
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MyOffice.Services.Account.Domain;
|
||||
using System.Collections.Generic;
|
||||
using Identity;
|
||||
|
||||
public class AccountService
|
||||
{
|
||||
@@ -29,6 +30,7 @@
|
||||
private readonly IItemRepository _itemRepository;
|
||||
private readonly IItemGlobalRepository _itemGlobalRepository;
|
||||
private readonly ItemService _itemService;
|
||||
private readonly IContextProvider _contextProvider;
|
||||
|
||||
public AccountService(
|
||||
ILogger<AccountService> logger,
|
||||
@@ -42,7 +44,8 @@
|
||||
IMotionRepository motionRepository,
|
||||
IItemRepository itemRepository,
|
||||
IItemGlobalRepository itemGlobalRepository,
|
||||
ItemService itemService
|
||||
ItemService itemService,
|
||||
IContextProvider contextProvider
|
||||
)
|
||||
{
|
||||
_logger = logger;
|
||||
@@ -57,6 +60,7 @@
|
||||
_itemRepository = itemRepository;
|
||||
_itemGlobalRepository = itemGlobalRepository;
|
||||
_itemService = itemService;
|
||||
_contextProvider = contextProvider;
|
||||
}
|
||||
|
||||
public List<AccountCategoryDto> GetAllCategories(Guid userId)
|
||||
@@ -70,7 +74,7 @@
|
||||
{
|
||||
var result = new Exec<AccountCategoryDto, GeneralExecStatus>(GeneralExecStatus.success);
|
||||
|
||||
var category = _accountCategoryRepository.Get(userId, id);
|
||||
var category = _accountCategoryRepository.Get(userId, id);
|
||||
|
||||
if (category == null)
|
||||
{
|
||||
@@ -528,13 +532,13 @@
|
||||
|
||||
if (account.AccessRights!.Any(x => x.User!.Email.EqualsIgnoreCase(email)))
|
||||
{
|
||||
return result.Set(AccessInviteStatus.account_not_found);
|
||||
return result.Set(AccessInviteStatus.access_exists);
|
||||
}
|
||||
|
||||
var access = _accountAccessInviteRepository.Get(userId, email);
|
||||
if (access != null)
|
||||
{
|
||||
return result.Set(AccessInviteStatus.access_exists);
|
||||
return result.Set(AccessInviteStatus.invite_exists);
|
||||
}
|
||||
|
||||
var invite = new AccountAccessInvite
|
||||
@@ -542,7 +546,8 @@
|
||||
Id = Guid.NewGuid(),
|
||||
CreatedOn = DateTime.UtcNow,
|
||||
UserId = userId,
|
||||
Email = email,
|
||||
AccountId = account.Id,
|
||||
Email = email.SafeTrim()!,
|
||||
IsAllowWrite = isAllowWrite,
|
||||
};
|
||||
|
||||
@@ -606,5 +611,75 @@
|
||||
return result.Set(_mapper.Map<AccountDto>(account));
|
||||
|
||||
}
|
||||
|
||||
public List<AccountAccessInviteDto> InvitesGet(string email)
|
||||
{
|
||||
return _mapper.Map<List<AccountAccessInviteDto>>(_accountAccessInviteRepository.GetActive(email).ToList());
|
||||
}
|
||||
|
||||
public Exec<AccountDto, InviteAcceptStatus> InviteAccept(Guid userId, Guid id, string name)
|
||||
{
|
||||
var result = new Exec<AccountDto, InviteAcceptStatus>(InviteAcceptStatus.success);
|
||||
|
||||
var invite = _accountAccessInviteRepository.Get(id);
|
||||
if (invite == null
|
||||
|| !invite.Email.EqualsIgnoreCase(_contextProvider.User.Email)
|
||||
|| invite.AcceptedOn.HasValue
|
||||
|| invite.RejectedOn.HasValue
|
||||
)
|
||||
{
|
||||
return result.Set(InviteAcceptStatus.invite_not_found);
|
||||
}
|
||||
|
||||
var account = _accountRepository.Get(invite.UserId, invite.AccountId);
|
||||
if (account == null)
|
||||
{
|
||||
return result.Set(InviteAcceptStatus.account_not_found);
|
||||
}
|
||||
|
||||
if (account.AccessRights!.Any(x => x.UserId == userId))
|
||||
{
|
||||
result.Set(InviteAcceptStatus.already_accepted);
|
||||
}
|
||||
else
|
||||
{
|
||||
_accountAccessRepository.Add(new AccountAccess
|
||||
{
|
||||
UserId = userId,
|
||||
AccountId = account.Id,
|
||||
OwnerId = invite.UserId,
|
||||
Name = name,
|
||||
IsAllowWrite = invite.IsAllowWrite,
|
||||
Type = AccountAccessTypeEnum.external,
|
||||
});
|
||||
}
|
||||
|
||||
invite.AcceptedOn = DateTime.UtcNow;
|
||||
_accountAccessInviteRepository.Update(invite);
|
||||
|
||||
account = _accountRepository.Get(userId, account.Id);
|
||||
|
||||
return result.Set(_mapper.Map<AccountDto>(account));
|
||||
}
|
||||
|
||||
public Exec<AccountAccessInviteDto, GeneralExecStatus> InviteReject(Guid id)
|
||||
{
|
||||
var result = new Exec<AccountAccessInviteDto, GeneralExecStatus>(GeneralExecStatus.success);
|
||||
|
||||
var invite = _accountAccessInviteRepository.Get(id);
|
||||
if (invite == null
|
||||
|| !invite.Email.EqualsIgnoreCase(_contextProvider.User.Email)
|
||||
|| invite.AcceptedOn.HasValue
|
||||
|| invite.RejectedOn.HasValue
|
||||
)
|
||||
{
|
||||
return result.Set(GeneralExecStatus.not_found);
|
||||
}
|
||||
|
||||
invite.RejectedOn = DateTime.UtcNow;
|
||||
_accountAccessInviteRepository.Update(invite);
|
||||
|
||||
return result.Set(_mapper.Map<AccountAccessInviteDto>(invite));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
namespace MyOffice.Services.Account.Domain;
|
||||
|
||||
using Core.Attributes;
|
||||
using Data.Models.Accounts;
|
||||
using Data.Models.Users;
|
||||
using Mapper;
|
||||
|
||||
[Link(typeof(AccountAccess))]
|
||||
[Link(typeof(AccountServiceProfile))]
|
||||
public class AccountAccessDto
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace MyOffice.Services.Account.Domain;
|
||||
|
||||
using Core.Attributes;
|
||||
using Data.Models.Accounts;
|
||||
|
||||
[Link(typeof(AccountAccessInvite))]
|
||||
public class AccountAccessInviteDto
|
||||
{
|
||||
public string Id { get; set; } = null!;
|
||||
public string Account { get; set; } = null!;
|
||||
public bool IsAllowWrite { get; set; }
|
||||
}
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
using MyOffice.Data.Models.Currencies;
|
||||
using System;
|
||||
using Data.Models.Accounts;
|
||||
|
||||
public class AccountDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid CurrentUserId { get; set; }
|
||||
public string CurrencyGlobalId { get; set; } = null!;
|
||||
public CurrencyGlobal? CurrencyGlobal { get; set; }
|
||||
public Guid CurrencyId { get; set; }
|
||||
@@ -20,4 +20,8 @@ public class AccountDto
|
||||
public string Type { get; set; } = null!;
|
||||
public List<AccountAccessDto>? AccessRights { get; set; }
|
||||
public List<AccountAccountCategoryDto>? Categories { get; set; }
|
||||
|
||||
|
||||
public Guid CurrentUserId { get; set; }
|
||||
public AccountAccess? AccountAccess { get; set; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace MyOffice.Services.Account.Domain
|
||||
{
|
||||
public enum InviteAcceptStatus
|
||||
{
|
||||
success,
|
||||
invite_not_found,
|
||||
account_not_found,
|
||||
already_accepted,
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,20 @@ public class AccountServiceProfile : Profile
|
||||
CreateMap<Account, AccountDto>()
|
||||
.ForMember(x => x.HasMotions, o => o.MapFrom(x => x.Motions!.Any()))
|
||||
.ForMember(x => x.CurrentUserId, o => o.MapFrom<UserIdResolver>())
|
||||
.ForMember(x => x.Type, o => o.MapFrom((src, dst) => src.AccessRights!.FirstOrDefault(x => x.UserId == dst.CurrentUserId)!.Type.ToString()))
|
||||
.ForMember(x => x.AccountAccess, o =>
|
||||
{
|
||||
o.MapFrom((src, dst) => src.AccessRights!.FirstOrDefault(x => x.UserId == dst.CurrentUserId));
|
||||
})
|
||||
.ForMember(x => x.Type, o =>
|
||||
{
|
||||
o.SetMappingOrder(1);
|
||||
o.MapFrom((src, dst) => dst.AccountAccess?.Type.ToString());
|
||||
})
|
||||
.ForMember(x => x.Name, o =>
|
||||
{
|
||||
o.SetMappingOrder(1);
|
||||
o.MapFrom((src, dst) => dst.AccountAccess?.Name ?? src.Name);
|
||||
})
|
||||
;
|
||||
|
||||
CreateMap<AccountDetailed, AccountDetailedDto>();
|
||||
@@ -27,5 +40,9 @@ public class AccountServiceProfile : Profile
|
||||
.ForMember(x => x.Id, o => o.MapFrom(x => x.Id))
|
||||
.ForMember(x => x.AllowDelete, o => o.MapFrom(x => !x.Accounts!.Any()))
|
||||
;
|
||||
|
||||
CreateMap<AccountAccessInvite, AccountAccessInviteDto>()
|
||||
.ForMember(x => x.Account, o => o.MapFrom(x => x.Account!.Name))
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ using Models.Account;
|
||||
using Services.Account;
|
||||
using Services.Account.Domain;
|
||||
using MyOffice.Web.Infrastructure.Attributes;
|
||||
using Services.Identity;
|
||||
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
@@ -19,16 +20,19 @@ public class SettingsAccountController : BaseApiController
|
||||
private readonly ILogger<SettingsAccountController> _logger;
|
||||
private readonly IMapper _mapper;
|
||||
private readonly AccountService _accountService;
|
||||
private readonly IContextProvider _contextProvider;
|
||||
|
||||
public SettingsAccountController(
|
||||
ILogger<SettingsAccountController> logger,
|
||||
IMapper mapper,
|
||||
AccountService accountService
|
||||
AccountService accountService,
|
||||
IContextProvider contextProvider
|
||||
)
|
||||
{
|
||||
_logger = logger;
|
||||
_mapper = mapper;
|
||||
_accountService = accountService;
|
||||
_contextProvider = contextProvider;
|
||||
}
|
||||
|
||||
[HttpGet("~/api/settings/account-categories")]
|
||||
@@ -251,8 +255,6 @@ public class SettingsAccountController : BaseApiController
|
||||
return ProblemBadRequest("Account not found.");
|
||||
|
||||
case AccessInviteStatus.access_exists:
|
||||
return ProblemBadRequest("Access allowed.");
|
||||
|
||||
case AccessInviteStatus.invite_exists:
|
||||
case AccessInviteStatus.success:
|
||||
return exec.Result!;
|
||||
@@ -279,6 +281,53 @@ public class SettingsAccountController : BaseApiController
|
||||
default:
|
||||
throw new NotSupportedException(exec.Status.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("~/api/settings/accounts/invites")]
|
||||
public List<AccountAccessInviteViewModel> AccountInvites()
|
||||
{
|
||||
var invites = _accountService.InvitesGet(_contextProvider.User.Email);
|
||||
|
||||
return _mapper.Map<List<AccountAccessInviteViewModel>>(invites);
|
||||
}
|
||||
|
||||
[HttpPost("~/api/settings/accounts/invites/{id}/accept")]
|
||||
public object AccountInviteAccept([AsGuid]string id, AccountInviteAcceptRequest request)
|
||||
{
|
||||
var exec = _accountService.InviteAccept(UserId, id.AsGuid(), request.Name);
|
||||
|
||||
switch (exec.Status)
|
||||
{
|
||||
case InviteAcceptStatus.invite_not_found:
|
||||
return ProblemBadRequest("Invite not found.");
|
||||
case InviteAcceptStatus.account_not_found:
|
||||
return ProblemBadRequest("Account not found.");
|
||||
|
||||
case InviteAcceptStatus.already_accepted:
|
||||
case InviteAcceptStatus.success:
|
||||
return _mapper.Map<AccountViewModel>(exec.Result!);
|
||||
|
||||
default:
|
||||
throw new NotSupportedException(exec.Status.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPost("~/api/settings/accounts/invites/{id}/reject")]
|
||||
public object AccountInviteReject([AsGuid] string id)
|
||||
{
|
||||
var exec = _accountService.InviteReject(id.AsGuid());
|
||||
|
||||
switch (exec.Status)
|
||||
{
|
||||
case GeneralExecStatus.not_found:
|
||||
case GeneralExecStatus.failure:
|
||||
return ProblemBadRequest("Invite not found.");
|
||||
|
||||
case GeneralExecStatus.success:
|
||||
return _mapper.Map<AccountAccessInviteViewModel>(exec.Result!);
|
||||
|
||||
default:
|
||||
throw new NotSupportedException(exec.Status.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace MyOffice.Web.Models.Account;
|
||||
|
||||
using Core.Attributes;
|
||||
using Services.Account.Domain;
|
||||
|
||||
[LinkFrom(typeof(AccountAccessInviteDto))]
|
||||
[LinkWith(typeof(AccountViewModelProfile))]
|
||||
public class AccountAccessInviteViewModel
|
||||
{
|
||||
public string? Id { get; set; }
|
||||
public string? Account { get; set; }
|
||||
public bool? AllowWrite { get; set; }
|
||||
}
|
||||
@@ -1,29 +1,16 @@
|
||||
namespace MyOffice.Web.Models.Account
|
||||
namespace MyOffice.Web.Models.Account;
|
||||
|
||||
using MyOffice.Core.Attributes;
|
||||
using MyOffice.Services.Account.Domain;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
[Link(typeof(AccountCategoryDto))]
|
||||
public class AccountCategoryViewModel
|
||||
{
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Core.Extensions;
|
||||
using Data.Models.Accounts;
|
||||
public string? Id { get; set; }
|
||||
|
||||
public class AccountCategoryViewModel
|
||||
{
|
||||
public string? Id { get; set; }
|
||||
[Required]
|
||||
public string? Name { get; set; }
|
||||
|
||||
[Required]
|
||||
public string? Name { get; set; }
|
||||
|
||||
public bool? AllowDelete { get; set; }
|
||||
}
|
||||
|
||||
public static class AccountCategoryViewModelExtensions
|
||||
{
|
||||
public static AccountCategoryViewModel ToModel(this AccountCategory input)
|
||||
{
|
||||
return new AccountCategoryViewModel
|
||||
{
|
||||
Id = input.Id.ToShort(),
|
||||
Name = input.Name,
|
||||
AllowDelete = !input.Accounts?.Any(),
|
||||
};
|
||||
}
|
||||
}
|
||||
public bool? AllowDelete { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace MyOffice.Web.Models.Account;
|
||||
|
||||
public class AccountInviteAcceptRequest
|
||||
{
|
||||
public string Name { get; set; } = null!;
|
||||
}
|
||||
@@ -3,11 +3,7 @@
|
||||
using AutoMapper;
|
||||
using MyOffice.Services.Identity;
|
||||
using Services.Account.Domain;
|
||||
using Services.Mapper;
|
||||
using System.Security.Cryptography;
|
||||
using Core.Extensions;
|
||||
using User;
|
||||
using static MyOffice.Web.Models.Account.AccountAccessViewModel;
|
||||
|
||||
public class CustomResolver : IValueResolver<AccountAccessDto, AccessRightsViewModel, bool>
|
||||
{
|
||||
@@ -61,11 +57,15 @@ public class AccountViewModelProfile : Profile
|
||||
(src, dst) => src.OwnerId == src.UserId))
|
||||
;
|
||||
|
||||
CreateMap<AccountAccessItemViewModel, AccountAccessDto>()
|
||||
CreateMap<AccountAccessViewModel.AccountAccessItemViewModel, AccountAccessDto>()
|
||||
.ForMember(x => x.IsAllowWrite, o => o.MapFrom(x => x.AllowWrite))
|
||||
;
|
||||
|
||||
CreateMap<AccountCategoryDto, AccountCategoryViewModel>()
|
||||
;
|
||||
|
||||
CreateMap<AccountAccessInviteDto, AccountAccessInviteViewModel>()
|
||||
.ForMember(x => x.AllowWrite, o => o.MapFrom(x => x.IsAllowWrite))
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -64,6 +64,13 @@ using MyOffice.Services.Mapper;
|
||||
//TODO: Response model from base type
|
||||
//TODO: XXXResult -> XXXStatus
|
||||
//TODO: SPA isAllowDelete -> allowDelete (remove is)
|
||||
//TODO: Repository auto registration
|
||||
//TODO: Services auto registration
|
||||
//TODO: openid-configuration failed - lock login
|
||||
//TODO: BUG some times after login redirect to dashboard but exists return url
|
||||
//TODO: email confirmation
|
||||
//TODO: email password reset
|
||||
//TODO: automapper -> Extension ToModel() ToDbo() FromModel() FromDbo()
|
||||
|
||||
public class Program
|
||||
{
|
||||
@@ -262,6 +269,7 @@ public class Program
|
||||
builder.Services.AddScoped<IAccountCategoryRepository, AccountCategoryRepository>();
|
||||
builder.Services.AddScoped<IAccountRepository, AccountRepository>();
|
||||
builder.Services.AddScoped<IAccountAccessRepository, AccountAccessRepository>();
|
||||
builder.Services.AddScoped<IAccountAccessInviteRepository, AccountAccessInviteRepository>();
|
||||
builder.Services.AddScoped<IAccountAccountCategoryRepository, AccountAccountCategoryRepository>();
|
||||
|
||||
builder.Services.AddScoped<IItemCategoryRepository, ItemCategoryRepository>();
|
||||
|
||||
Reference in New Issue
Block a user