Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,9 @@ The structure of the files are as follows (`XXX` means redacted):
"JwtSettings": {
"Issuer": "AnalySim",
"Secret": "XXX",
"ExpireTime": 60,
"Audience": "https://www.analysim.tech"
"ExpireTime": 10,
"Audience": "https://www.analysim.tech",
"RefreshTokenExpireDays": 14
},
"UserQuota": 100000000,
"registrationCodes": [ "123" ],
Expand Down
43 changes: 43 additions & 0 deletions src/Analysim.Core/Entities/RefreshToken.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace Core.Entities
{
public class RefreshToken
{
public int RefreshTokenID { get; set; }

public int UserID { get; set; }

public User User { get; set; }

[Required]
public string TokenHash { get; set; }

public Guid TokenFamilyID { get; set; }

public DateTime CreatedAt { get; set; }

public DateTime ExpiresAt { get; set; }

public DateTime? RevokedAt { get; set; }

public string ReplacedByTokenHash { get; set; }

public string RevokedReason { get; set; }

public string CreatedByIp { get; set; }

public string RevokedByIp { get; set; }

[NotMapped]
public bool IsExpired => DateTime.UtcNow >= ExpiresAt;

[NotMapped]
public bool IsRevoked => RevokedAt.HasValue;

[NotMapped]
public bool IsActive => !IsRevoked && !IsExpired;
}
}
2 changes: 2 additions & 0 deletions src/Analysim.Core/Entities/User.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public class User : IdentityUser<int>
// Logs
public ICollection<ProjectLog> ProjectLogs { get; set; } = new List<ProjectLog>();

public ICollection<RefreshToken> RefreshTokens { get; set; } = new List<RefreshToken>();

public string RegistrationSurvey {get; set;}

}
Expand Down
1 change: 1 addition & 0 deletions src/Analysim.Core/Helper/JwtSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ public class JwtSettings
public string Secret { get; set; }
public string ExpireTime { get; set; }
public string Audience { get; set; }
public int RefreshTokenExpireDays { get; set; } = 14;
}
}
18 changes: 18 additions & 0 deletions src/Analysim.Infrastructure/Data/ApplicationDbContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ namespace Infrastructure.Data
{
public class ApplicationDbContext : IdentityDbContext<User, IdentityRole<int>, int>
{
public DbSet<RefreshToken> RefreshTokens { get; set; }

public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{

Expand All @@ -24,6 +26,16 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
modelBuilder.Entity<UserUser>().HasKey(uu => new { uu.UserID, uu.FollowerID });
modelBuilder.Entity<NotebookContent>().HasKey(nc => new { nc.NotebookID, nc.Version });

modelBuilder.Entity<RefreshToken>()
.HasIndex(rt => rt.TokenHash)
.IsUnique();

modelBuilder.Entity<RefreshToken>()
.HasIndex(rt => rt.UserID);

modelBuilder.Entity<RefreshToken>()
.HasIndex(rt => rt.TokenFamilyID);

// Many To Many Relationship (ProjectUser -> User)
modelBuilder.Entity<ProjectUser>()
.HasOne<User>(i => i.User)
Expand Down Expand Up @@ -66,6 +78,12 @@ protected override void OnModelCreating(ModelBuilder modelBuilder)
.WithOne(u => u.User)
.HasForeignKey(u => u.UserID);

modelBuilder.Entity<User>()
.HasMany(u => u.RefreshTokens)
.WithOne(rt => rt.User)
.HasForeignKey(rt => rt.UserID)
.OnDelete(DeleteBehavior.Cascade);

// One To Many Relationship (Project -> Blob)
modelBuilder.Entity<Project>()
.HasMany(p => p.BlobFiles)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,57 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.ToTable("Publications");
});

modelBuilder.Entity("Core.Entities.RefreshToken", b =>
{
b.Property<int>("RefreshTokenID")
.ValueGeneratedOnAdd()
.HasColumnType("integer");

NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("RefreshTokenID"));

b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone");

b.Property<string>("CreatedByIp")
.HasColumnType("text");

b.Property<DateTime>("ExpiresAt")
.HasColumnType("timestamp with time zone");

b.Property<string>("ReplacedByTokenHash")
.HasColumnType("text");

b.Property<DateTime?>("RevokedAt")
.HasColumnType("timestamp with time zone");

b.Property<string>("RevokedByIp")
.HasColumnType("text");

b.Property<string>("RevokedReason")
.HasColumnType("text");

b.Property<Guid>("TokenFamilyID")
.HasColumnType("uuid");

b.Property<string>("TokenHash")
.IsRequired()
.HasColumnType("text");

b.Property<int>("UserID")
.HasColumnType("integer");

b.HasKey("RefreshTokenID");

b.HasIndex("TokenFamilyID");

b.HasIndex("TokenHash")
.IsUnique();

b.HasIndex("UserID");

b.ToTable("RefreshTokens");
});

modelBuilder.Entity("Core.Entities.Tag", b =>
{
b.Property<int>("TagID")
Expand Down Expand Up @@ -979,6 +1030,17 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.Navigation("Project");
});

modelBuilder.Entity("Core.Entities.RefreshToken", b =>
{
b.HasOne("Core.Entities.User", "User")
.WithMany("RefreshTokens")
.HasForeignKey("UserID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();

b.Navigation("User");
});

modelBuilder.Entity("Core.Entities.UserUser", b =>
{
b.HasOne("Core.Entities.User", "Follower")
Expand Down Expand Up @@ -1114,6 +1176,8 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.Navigation("ProjectLogs");

b.Navigation("ProjectUsers");

b.Navigation("RefreshTokens");
});
#pragma warning restore 612, 618
}
Expand Down
Loading
Loading