mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-15 09:42:56 -07:00
Some small refresh token work #865
This commit is contained in:
parent
8b3c57431c
commit
24e424f004
11 changed files with 158 additions and 52 deletions
|
@ -94,6 +94,7 @@ namespace Ombi.DependencyInjection
|
||||||
services.AddTransient<IMovieRequestRepository, MovieRequestRepository>();
|
services.AddTransient<IMovieRequestRepository, MovieRequestRepository>();
|
||||||
services.AddTransient<IAuditRepository, AuditRepository>();
|
services.AddTransient<IAuditRepository, AuditRepository>();
|
||||||
services.AddTransient<IApplicationConfigRepository, ApplicationConfigRepository>();
|
services.AddTransient<IApplicationConfigRepository, ApplicationConfigRepository>();
|
||||||
|
services.AddTransient<ITokenRepository, TokenRepository>();
|
||||||
services.AddTransient(typeof(ISettingsService<>), typeof(SettingsService<>));
|
services.AddTransient(typeof(ISettingsService<>), typeof(SettingsService<>));
|
||||||
}
|
}
|
||||||
public static void RegisterServices(this IServiceCollection services)
|
public static void RegisterServices(this IServiceCollection services)
|
||||||
|
|
|
@ -29,5 +29,6 @@ namespace Ombi.Store.Context
|
||||||
DbSet<ChildRequests> ChildRequests { get; set; }
|
DbSet<ChildRequests> ChildRequests { get; set; }
|
||||||
DbSet<MovieIssues> MovieIssues { get; set; }
|
DbSet<MovieIssues> MovieIssues { get; set; }
|
||||||
DbSet<TvIssues> TvIssues { get; set; }
|
DbSet<TvIssues> TvIssues { get; set; }
|
||||||
|
DbSet<Tokens> Tokens { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -35,6 +35,7 @@ namespace Ombi.Store.Context
|
||||||
public DbSet<TvIssues> TvIssues { get; set; }
|
public DbSet<TvIssues> TvIssues { get; set; }
|
||||||
|
|
||||||
public DbSet<Audit> Audit { get; set; }
|
public DbSet<Audit> Audit { get; set; }
|
||||||
|
public DbSet<Tokens> Tokens { get; set; }
|
||||||
|
|
||||||
public DbSet<ApplicationConfiguration> ApplicationConfigurations { get; set; }
|
public DbSet<ApplicationConfiguration> ApplicationConfigurations { get; set; }
|
||||||
|
|
||||||
|
|
14
src/Ombi.Store/Entities/Tokens.cs
Normal file
14
src/Ombi.Store/Entities/Tokens.cs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Ombi.Store.Entities
|
||||||
|
{
|
||||||
|
public class Tokens : Entity
|
||||||
|
{
|
||||||
|
public string Token { get; set; }
|
||||||
|
public string UserId { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
[ForeignKey(nameof(UserId))]
|
||||||
|
public OmbiUser User { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,7 +10,7 @@ using Ombi.Helpers;
|
||||||
namespace Ombi.Store.Migrations
|
namespace Ombi.Store.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(OmbiContext))]
|
[DbContext(typeof(OmbiContext))]
|
||||||
[Migration("20170801143617_Inital")]
|
[Migration("20170811145836_Inital")]
|
||||||
partial class Inital
|
partial class Inital
|
||||||
{
|
{
|
||||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
@ -449,6 +449,22 @@ namespace Ombi.Store.Migrations
|
||||||
b.ToTable("TvRequests");
|
b.ToTable("TvRequests");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Tokens", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Token");
|
||||||
|
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("Tokens");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b =>
|
modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
|
@ -581,6 +597,13 @@ namespace Ombi.Store.Migrations
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Tokens", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b =>
|
modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season")
|
b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season")
|
|
@ -296,6 +296,26 @@ namespace Ombi.Store.Migrations
|
||||||
onDelete: ReferentialAction.Restrict);
|
onDelete: ReferentialAction.Restrict);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Tokens",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
Token = table.Column<string>(nullable: true),
|
||||||
|
UserId = table.Column<string>(nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Tokens", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Tokens_AspNetUsers_UserId",
|
||||||
|
column: x => x.UserId,
|
||||||
|
principalTable: "AspNetUsers",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
});
|
||||||
|
|
||||||
migrationBuilder.CreateTable(
|
migrationBuilder.CreateTable(
|
||||||
name: "PlexSeasonsContent",
|
name: "PlexSeasonsContent",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
|
@ -531,6 +551,11 @@ namespace Ombi.Store.Migrations
|
||||||
table: "TvIssues",
|
table: "TvIssues",
|
||||||
column: "TvId");
|
column: "TvId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Tokens_UserId",
|
||||||
|
table: "Tokens",
|
||||||
|
column: "UserId");
|
||||||
|
|
||||||
migrationBuilder.CreateIndex(
|
migrationBuilder.CreateIndex(
|
||||||
name: "IX_EpisodeRequests_SeasonId",
|
name: "IX_EpisodeRequests_SeasonId",
|
||||||
table: "EpisodeRequests",
|
table: "EpisodeRequests",
|
||||||
|
@ -583,6 +608,9 @@ namespace Ombi.Store.Migrations
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "TvIssues");
|
name: "TvIssues");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Tokens");
|
||||||
|
|
||||||
migrationBuilder.DropTable(
|
migrationBuilder.DropTable(
|
||||||
name: "EpisodeRequests");
|
name: "EpisodeRequests");
|
||||||
|
|
|
@ -448,6 +448,22 @@ namespace Ombi.Store.Migrations
|
||||||
b.ToTable("TvRequests");
|
b.ToTable("TvRequests");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Tokens", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<string>("Token");
|
||||||
|
|
||||||
|
b.Property<string>("UserId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId");
|
||||||
|
|
||||||
|
b.ToTable("Tokens");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b =>
|
modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
|
@ -580,6 +596,13 @@ namespace Ombi.Store.Migrations
|
||||||
.OnDelete(DeleteBehavior.Cascade);
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Ombi.Store.Entities.Tokens", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Ombi.Store.Entities.OmbiUser", "User")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UserId");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b =>
|
modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season")
|
b.HasOne("Ombi.Store.Repository.Requests.SeasonRequests", "Season")
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Ombi.Store.Entities;
|
using Ombi.Store.Entities;
|
||||||
|
|
||||||
namespace Ombi.Store.Repository
|
namespace Ombi.Store.Repository
|
||||||
{
|
{
|
||||||
//public interface ITokenRepository
|
public interface ITokenRepository
|
||||||
//{
|
{
|
||||||
// Task CreateToken(EmailTokens token);
|
Task CreateToken(Tokens token);
|
||||||
// Task<EmailTokens> GetToken(Guid tokenId);
|
IQueryable<Tokens> GetToken(string tokenId);
|
||||||
//}
|
}
|
||||||
}
|
}
|
|
@ -2,29 +2,29 @@
|
||||||
using Ombi.Store.Context;
|
using Ombi.Store.Context;
|
||||||
using Ombi.Store.Entities;
|
using Ombi.Store.Entities;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace Ombi.Store.Repository
|
namespace Ombi.Store.Repository
|
||||||
{
|
{
|
||||||
//public class TokenRepository : ITokenRepository
|
public class TokenRepository : ITokenRepository
|
||||||
//{
|
{
|
||||||
// public TokenRepository(IOmbiContext db)
|
public TokenRepository(IOmbiContext db)
|
||||||
// {
|
{
|
||||||
// Db = db;
|
Db = db;
|
||||||
// }
|
}
|
||||||
|
|
||||||
// private IOmbiContext Db { get; }
|
private IOmbiContext Db { get; }
|
||||||
|
|
||||||
// public async Task CreateToken(EmailTokens token)
|
public async Task CreateToken(Tokens token)
|
||||||
// {
|
{
|
||||||
// token.Token = Guid.NewGuid();
|
await Db.Tokens.AddAsync(token);
|
||||||
// await Db.EmailTokens.AddAsync(token);
|
await Db.SaveChangesAsync();
|
||||||
// await Db.SaveChangesAsync();
|
}
|
||||||
// }
|
|
||||||
|
|
||||||
// public async Task<EmailTokens> GetToken(Guid tokenId)
|
public IQueryable<Tokens> GetToken(string tokenId)
|
||||||
// {
|
{
|
||||||
// return await Db.EmailTokens.FirstOrDefaultAsync(x => x.Token == tokenId);
|
return Db.Tokens.Where(x => x.Token == tokenId);
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,18 +20,20 @@ namespace Ombi.Controllers
|
||||||
public class TokenController
|
public class TokenController
|
||||||
{
|
{
|
||||||
public TokenController(UserManager<OmbiUser> um, IOptions<TokenAuthentication> ta,
|
public TokenController(UserManager<OmbiUser> um, IOptions<TokenAuthentication> ta,
|
||||||
IApplicationConfigRepository config, IAuditRepository audit)
|
IApplicationConfigRepository config, IAuditRepository audit, ITokenRepository token)
|
||||||
{
|
{
|
||||||
UserManager = um;
|
_userManager = um;
|
||||||
TokenAuthenticationOptions = ta.Value;
|
_tokenAuthenticationOptions = ta.Value;
|
||||||
Config = config;
|
_config = config;
|
||||||
Audit = audit;
|
_audit = audit;
|
||||||
|
_token = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
private TokenAuthentication TokenAuthenticationOptions { get; }
|
private readonly TokenAuthentication _tokenAuthenticationOptions;
|
||||||
private IApplicationConfigRepository Config { get; }
|
private IApplicationConfigRepository _config;
|
||||||
private IAuditRepository Audit { get; }
|
private readonly IAuditRepository _audit;
|
||||||
private UserManager<OmbiUser> UserManager { get; }
|
private readonly ITokenRepository _token;
|
||||||
|
private readonly UserManager<OmbiUser> _userManager;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the token.
|
/// Gets the token.
|
||||||
|
@ -41,30 +43,20 @@ namespace Ombi.Controllers
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IActionResult> GetToken([FromBody] UserAuthModel model)
|
public async Task<IActionResult> GetToken([FromBody] UserAuthModel model)
|
||||||
{
|
{
|
||||||
await Audit.Record(AuditType.None, AuditArea.Authentication,
|
await _audit.Record(AuditType.None, AuditArea.Authentication,
|
||||||
$"Username {model.Username} attempting to authenticate");
|
$"Username {model.Username} attempting to authenticate");
|
||||||
|
|
||||||
var user = await UserManager.FindByNameAsync(model.Username);
|
var user = await _userManager.FindByNameAsync(model.Username);
|
||||||
|
|
||||||
if (user == null)
|
if (user == null)
|
||||||
{
|
{
|
||||||
return null;
|
return new UnauthorizedResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify Password
|
// Verify Password
|
||||||
if ((await UserManager.CheckPasswordAsync(user, model.Password)))
|
if (await _userManager.CheckPasswordAsync(user, model.Password))
|
||||||
{
|
{
|
||||||
// Get the url
|
var roles = await _userManager.GetRolesAsync(user);
|
||||||
var url = Config.Get(ConfigurationTypes.Url);
|
|
||||||
var port = Config.Get(ConfigurationTypes.Port);
|
|
||||||
|
|
||||||
#if !DEBUG
|
|
||||||
var audience = $"{url}:{port}";
|
|
||||||
#else
|
|
||||||
|
|
||||||
var audience = $"http://localhost:52038/";
|
|
||||||
#endif
|
|
||||||
var roles = await UserManager.GetRolesAsync(user);
|
|
||||||
|
|
||||||
var claims = new List<Claim>
|
var claims = new List<Claim>
|
||||||
{
|
{
|
||||||
|
@ -74,7 +66,7 @@ namespace Ombi.Controllers
|
||||||
};
|
};
|
||||||
claims.AddRange(roles.Select(role => new Claim("role", role)));
|
claims.AddRange(roles.Select(role => new Claim("role", role)));
|
||||||
|
|
||||||
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(TokenAuthenticationOptions.SecretKey));
|
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenAuthenticationOptions.SecretKey));
|
||||||
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
|
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
|
||||||
|
|
||||||
var token = new JwtSecurityToken(
|
var token = new JwtSecurityToken(
|
||||||
|
@ -83,15 +75,21 @@ namespace Ombi.Controllers
|
||||||
signingCredentials: creds,
|
signingCredentials: creds,
|
||||||
audience: "Ombi", issuer:"Ombi"
|
audience: "Ombi", issuer:"Ombi"
|
||||||
);
|
);
|
||||||
|
var accessToken = new JwtSecurityTokenHandler().WriteToken(token);
|
||||||
|
if (model.RememberMe)
|
||||||
|
{
|
||||||
|
// Save the token so we can refresh it later
|
||||||
|
await _token.CreateToken(new Tokens() {Token = accessToken, User = user});
|
||||||
|
}
|
||||||
|
|
||||||
return new JsonResult(new
|
return new JsonResult(new
|
||||||
{
|
{
|
||||||
access_token = new JwtSecurityTokenHandler().WriteToken(token),
|
access_token = accessToken,
|
||||||
expiration = token.ValidTo
|
expiration = token.ValidTo
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return new UnauthorizedResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -101,10 +99,25 @@ namespace Ombi.Controllers
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// <exception cref="NotImplementedException"></exception>
|
/// <exception cref="NotImplementedException"></exception>
|
||||||
[HttpPost("refresh")]
|
[HttpPost("refresh")]
|
||||||
public async Task<IActionResult> RefreshToken([FromBody] UserAuthModel model)
|
public async Task<IActionResult> RefreshToken([FromBody] TokenRefresh token)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Check if token exists
|
||||||
|
var dbToken = _token.GetToken(token.Token).FirstOrDefault();
|
||||||
|
if (dbToken == null)
|
||||||
|
{
|
||||||
|
return new UnauthorizedResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class TokenRefresh
|
||||||
|
{
|
||||||
|
public string Token { get; set; }
|
||||||
|
public string Userename { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,5 +4,6 @@
|
||||||
{
|
{
|
||||||
public string Username { get; set; }
|
public string Username { get; set; }
|
||||||
public string Password { get; set; }
|
public string Password { get; set; }
|
||||||
|
public bool RememberMe { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue