mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-16 02:02:55 -07:00
Still a lot of work to do on the frontend for this.
This commit is contained in:
parent
8cf5a4c1fd
commit
b04344dd17
25 changed files with 952 additions and 476 deletions
|
@ -10,8 +10,8 @@
|
|||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="2.0.1" />
|
||||
<PackageReference Include="Hangfire" Version="1.6.14" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="1.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="1.1.2" />
|
||||
<PackageReference Include="MiniProfiler.AspNetCore" Version="4.0.0-alpha6-79" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
|
||||
<PackageReference Include="System.Diagnostics.Process" Version="4.3.0" />
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="1.1.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="1.1.0" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace Ombi.Mapping.Profiles
|
|||
|
||||
CreateMap<Claim, ClaimCheckboxes>().ConvertUsing<ClaimsConverter>();
|
||||
|
||||
CreateMap<UserDto, UserViewModel>().ForMember(x => x.Password, opt => opt.Ignore());
|
||||
CreateMap<OmbiUser, UserViewModel>().ForMember(x => x.Password, opt => opt.Ignore());
|
||||
|
||||
CreateMap<ClaimCheckboxes, Claim>()
|
||||
.ConstructUsing(checkbox => checkbox.Enabled ? new Claim(ClaimTypes.Role, checkbox.Value) : new Claim(ClaimTypes.Country, ""));
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace Ombi.Store.Context
|
|||
DbSet<PlexContent> PlexContent { get; set; }
|
||||
DbSet<RadarrCache> RadarrCache { get; set; }
|
||||
DatabaseFacade Database { get; }
|
||||
DbSet<User> Users { get; set; }
|
||||
DbSet<User> OldUsers { get; set; }
|
||||
EntityEntry<T> Entry<T>(T entry) where T : class;
|
||||
EntityEntry<TEntity> Attach<TEntity>(TEntity entity) where TEntity : class;
|
||||
DbSet<TEntity> Set<TEntity>() where TEntity : class;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Ombi.Helpers;
|
||||
using Ombi.Store.Entities;
|
||||
|
@ -7,7 +8,7 @@ using Ombi.Store.Entities.Requests;
|
|||
|
||||
namespace Ombi.Store.Context
|
||||
{
|
||||
public sealed class OmbiContext : DbContext, IOmbiContext
|
||||
public sealed class OmbiContext : IdentityDbContext<OmbiUser>, IOmbiContext
|
||||
{
|
||||
private static bool _created;
|
||||
public OmbiContext()
|
||||
|
@ -19,10 +20,12 @@ namespace Ombi.Store.Context
|
|||
|
||||
// Add the notifcation templates
|
||||
AddAllTemplates();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public DbSet<GlobalSettings> Settings { get; set; }
|
||||
public DbSet<User> Users { get; set; }
|
||||
public DbSet<User> OldUsers { get; set; }
|
||||
public DbSet<PlexContent> PlexContent { get; set; }
|
||||
public DbSet<RadarrCache> RadarrCache { get; set; }
|
||||
public DbSet<NotificationTemplates> NotificationTemplates { get; set; }
|
||||
|
|
14
src/Ombi.Store/Entities/OmbiUser.cs
Normal file
14
src/Ombi.Store/Entities/OmbiUser.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
|
||||
namespace Ombi.Store.Entities
|
||||
{
|
||||
public class OmbiUser : IdentityUser
|
||||
{
|
||||
public string Alias { get; set; }
|
||||
public UserType UserType { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public string UserAlias => string.IsNullOrEmpty(Alias) ? UserName : Alias;
|
||||
}
|
||||
}
|
|
@ -10,13 +10,142 @@ using Ombi.Store.Entities;
|
|||
namespace Ombi.Store.Migrations
|
||||
{
|
||||
[DbContext(typeof(OmbiContext))]
|
||||
[Migration("20170703134019_Initial")]
|
||||
[Migration("20170712080109_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "1.1.1");
|
||||
.HasAnnotation("ProductVersion", "1.1.2");
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken();
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("ClaimType");
|
||||
|
||||
b.Property<string>("ClaimValue");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("ClaimType");
|
||||
|
||||
b.Property<string>("ClaimValue");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider");
|
||||
|
||||
b.Property<string>("ProviderKey");
|
||||
|
||||
b.Property<string>("ProviderDisplayName");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId");
|
||||
|
||||
b.Property<string>("RoleId");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId");
|
||||
|
||||
b.Property<string>("LoginProvider");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.Property<string>("Value");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.EmailTokens", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<DateTime>("DateUsed");
|
||||
|
||||
b.Property<Guid>("Token");
|
||||
|
||||
b.Property<bool>("Used");
|
||||
|
||||
b.Property<int>("UserId");
|
||||
|
||||
b.Property<DateTime>("ValidUntil");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("EmailTokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b =>
|
||||
{
|
||||
|
@ -52,6 +181,60 @@ namespace Ombi.Store.Migrations
|
|||
b.ToTable("NotificationTemplates");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("AccessFailedCount");
|
||||
|
||||
b.Property<string>("Alias");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken();
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<bool>("EmailConfirmed");
|
||||
|
||||
b.Property<bool>("LockoutEnabled");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<string>("PasswordHash");
|
||||
|
||||
b.Property<string>("PhoneNumber");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed");
|
||||
|
||||
b.Property<string>("SecurityStamp");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<int>("UserType");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasName("UserNameIndex");
|
||||
|
||||
b.ToTable("AspNetUsers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.PlexContent", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
|
@ -131,6 +314,8 @@ namespace Ombi.Store.Migrations
|
|||
|
||||
b.Property<int>("RequestedUserId");
|
||||
|
||||
b.Property<string>("Title");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ParentRequestId");
|
||||
|
@ -273,7 +458,7 @@ namespace Ombi.Store.Migrations
|
|||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Users");
|
||||
b.ToTable("OldUsers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b =>
|
||||
|
@ -320,6 +505,51 @@ namespace Ombi.Store.Migrations
|
|||
b.ToTable("SeasonRequests");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
|
||||
.WithMany("Claims")
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||
.WithMany("Claims")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||
.WithMany("Logins")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
|
||||
.WithMany("Users")
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||
.WithMany("Roles")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.EmailTokens", b =>
|
||||
{
|
||||
b.HasOne("Ombi.Store.Entities.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
|
||||
{
|
||||
b.HasOne("Ombi.Store.Entities.PlexContent")
|
|
@ -8,6 +8,34 @@ namespace Ombi.Store.Migrations
|
|||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetRoles",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false),
|
||||
ConcurrencyStamp = table.Column<string>(nullable: true),
|
||||
Name = table.Column<string>(maxLength: 256, nullable: true),
|
||||
NormalizedName = table.Column<string>(maxLength: 256, nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetUserTokens",
|
||||
columns: table => new
|
||||
{
|
||||
UserId = table.Column<string>(nullable: false),
|
||||
LoginProvider = table.Column<string>(nullable: false),
|
||||
Name = table.Column<string>(nullable: false),
|
||||
Value = table.Column<string>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "GlobalSettings",
|
||||
columns: table => new
|
||||
|
@ -39,6 +67,33 @@ namespace Ombi.Store.Migrations
|
|||
table.PrimaryKey("PK_NotificationTemplates", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetUsers",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<string>(nullable: false),
|
||||
AccessFailedCount = table.Column<int>(nullable: false),
|
||||
Alias = table.Column<string>(nullable: true),
|
||||
ConcurrencyStamp = table.Column<string>(nullable: true),
|
||||
Email = table.Column<string>(maxLength: 256, nullable: true),
|
||||
EmailConfirmed = table.Column<bool>(nullable: false),
|
||||
LockoutEnabled = table.Column<bool>(nullable: false),
|
||||
LockoutEnd = table.Column<DateTimeOffset>(nullable: true),
|
||||
NormalizedEmail = table.Column<string>(maxLength: 256, nullable: true),
|
||||
NormalizedUserName = table.Column<string>(maxLength: 256, nullable: true),
|
||||
PasswordHash = table.Column<string>(nullable: true),
|
||||
PhoneNumber = table.Column<string>(nullable: true),
|
||||
PhoneNumberConfirmed = table.Column<bool>(nullable: false),
|
||||
SecurityStamp = table.Column<string>(nullable: true),
|
||||
TwoFactorEnabled = table.Column<bool>(nullable: false),
|
||||
UserName = table.Column<string>(maxLength: 256, nullable: true),
|
||||
UserType = table.Column<int>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PlexContent",
|
||||
columns: table => new
|
||||
|
@ -92,7 +147,7 @@ namespace Ombi.Store.Migrations
|
|||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Users",
|
||||
name: "OldUsers",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
|
@ -107,7 +162,93 @@ namespace Ombi.Store.Migrations
|
|||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Users", x => x.Id);
|
||||
table.PrimaryKey("PK_OldUsers", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetRoleClaims",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
ClaimType = table.Column<string>(nullable: true),
|
||||
ClaimValue = table.Column<string>(nullable: true),
|
||||
RoleId = table.Column<string>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
|
||||
column: x => x.RoleId,
|
||||
principalTable: "AspNetRoles",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetUserClaims",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
ClaimType = table.Column<string>(nullable: true),
|
||||
ClaimValue = table.Column<string>(nullable: true),
|
||||
UserId = table.Column<string>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetUserClaims_AspNetUsers_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetUserLogins",
|
||||
columns: table => new
|
||||
{
|
||||
LoginProvider = table.Column<string>(nullable: false),
|
||||
ProviderKey = table.Column<string>(nullable: false),
|
||||
ProviderDisplayName = table.Column<string>(nullable: true),
|
||||
UserId = table.Column<string>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetUserLogins_AspNetUsers_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetUserRoles",
|
||||
columns: table => new
|
||||
{
|
||||
UserId = table.Column<string>(nullable: false),
|
||||
RoleId = table.Column<string>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
|
||||
column: x => x.RoleId,
|
||||
principalTable: "AspNetRoles",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
|
@ -132,6 +273,29 @@ namespace Ombi.Store.Migrations
|
|||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "EmailTokens",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
DateUsed = table.Column<DateTime>(nullable: false),
|
||||
Token = table.Column<Guid>(nullable: false),
|
||||
Used = table.Column<bool>(nullable: false),
|
||||
UserId = table.Column<int>(nullable: false),
|
||||
ValidUntil = table.Column<DateTime>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_EmailTokens", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_EmailTokens_OldUsers_UserId",
|
||||
column: x => x.UserId,
|
||||
principalTable: "OldUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ChildRequests",
|
||||
columns: table => new
|
||||
|
@ -159,9 +323,9 @@ namespace Ombi.Store.Migrations
|
|||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_ChildRequests_Users_RequestedUserId",
|
||||
name: "FK_ChildRequests_OldUsers_RequestedUserId",
|
||||
column: x => x.RequestedUserId,
|
||||
principalTable: "Users",
|
||||
principalTable: "OldUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
@ -192,9 +356,9 @@ namespace Ombi.Store.Migrations
|
|||
{
|
||||
table.PrimaryKey("PK_MovieRequests", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_MovieRequests_Users_RequestedUserId",
|
||||
name: "FK_MovieRequests_OldUsers_RequestedUserId",
|
||||
column: x => x.RequestedUserId,
|
||||
principalTable: "Users",
|
||||
principalTable: "OldUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
@ -301,6 +465,48 @@ namespace Ombi.Store.Migrations
|
|||
onDelete: ReferentialAction.Cascade);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "RoleNameIndex",
|
||||
table: "AspNetRoles",
|
||||
column: "NormalizedName",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AspNetRoleClaims_RoleId",
|
||||
table: "AspNetRoleClaims",
|
||||
column: "RoleId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AspNetUserClaims_UserId",
|
||||
table: "AspNetUserClaims",
|
||||
column: "UserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AspNetUserLogins_UserId",
|
||||
table: "AspNetUserLogins",
|
||||
column: "UserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_AspNetUserRoles_RoleId",
|
||||
table: "AspNetUserRoles",
|
||||
column: "RoleId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_EmailTokens_UserId",
|
||||
table: "EmailTokens",
|
||||
column: "UserId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "EmailIndex",
|
||||
table: "AspNetUsers",
|
||||
column: "NormalizedEmail");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "UserNameIndex",
|
||||
table: "AspNetUsers",
|
||||
column: "NormalizedUserName",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PlexSeasonsContent_PlexContentId",
|
||||
table: "PlexSeasonsContent",
|
||||
|
@ -354,6 +560,24 @@ namespace Ombi.Store.Migrations
|
|||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetRoleClaims");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetUserClaims");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetUserLogins");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetUserRoles");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetUserTokens");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "EmailTokens");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "GlobalSettings");
|
||||
|
||||
|
@ -375,6 +599,12 @@ namespace Ombi.Store.Migrations
|
|||
migrationBuilder.DropTable(
|
||||
name: "EpisodeRequests");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetRoles");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetUsers");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "PlexContent");
|
||||
|
||||
|
@ -391,7 +621,7 @@ namespace Ombi.Store.Migrations
|
|||
name: "TvRequests");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Users");
|
||||
name: "OldUsers");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,7 +15,136 @@ namespace Ombi.Store.Migrations
|
|||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "1.1.1");
|
||||
.HasAnnotation("ProductVersion", "1.1.2");
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken();
|
||||
|
||||
b.Property<string>("Name")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<string>("NormalizedName")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedName")
|
||||
.IsUnique()
|
||||
.HasName("RoleNameIndex");
|
||||
|
||||
b.ToTable("AspNetRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("ClaimType");
|
||||
|
||||
b.Property<string>("ClaimValue");
|
||||
|
||||
b.Property<string>("RoleId")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetRoleClaims");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("ClaimType");
|
||||
|
||||
b.Property<string>("ClaimValue");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserClaims");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.Property<string>("LoginProvider");
|
||||
|
||||
b.Property<string>("ProviderKey");
|
||||
|
||||
b.Property<string>("ProviderDisplayName");
|
||||
|
||||
b.Property<string>("UserId")
|
||||
.IsRequired();
|
||||
|
||||
b.HasKey("LoginProvider", "ProviderKey");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("AspNetUserLogins");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId");
|
||||
|
||||
b.Property<string>("RoleId");
|
||||
|
||||
b.HasKey("UserId", "RoleId");
|
||||
|
||||
b.HasIndex("RoleId");
|
||||
|
||||
b.ToTable("AspNetUserRoles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserToken<string>", b =>
|
||||
{
|
||||
b.Property<string>("UserId");
|
||||
|
||||
b.Property<string>("LoginProvider");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.Property<string>("Value");
|
||||
|
||||
b.HasKey("UserId", "LoginProvider", "Name");
|
||||
|
||||
b.ToTable("AspNetUserTokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.EmailTokens", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<DateTime>("DateUsed");
|
||||
|
||||
b.Property<Guid>("Token");
|
||||
|
||||
b.Property<bool>("Used");
|
||||
|
||||
b.Property<int>("UserId");
|
||||
|
||||
b.Property<DateTime>("ValidUntil");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
b.ToTable("EmailTokens");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.GlobalSettings", b =>
|
||||
{
|
||||
|
@ -51,6 +180,60 @@ namespace Ombi.Store.Migrations
|
|||
b.ToTable("NotificationTemplates");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.OmbiUser", b =>
|
||||
{
|
||||
b.Property<string>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int>("AccessFailedCount");
|
||||
|
||||
b.Property<string>("Alias");
|
||||
|
||||
b.Property<string>("ConcurrencyStamp")
|
||||
.IsConcurrencyToken();
|
||||
|
||||
b.Property<string>("Email")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<bool>("EmailConfirmed");
|
||||
|
||||
b.Property<bool>("LockoutEnabled");
|
||||
|
||||
b.Property<DateTimeOffset?>("LockoutEnd");
|
||||
|
||||
b.Property<string>("NormalizedEmail")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<string>("NormalizedUserName")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<string>("PasswordHash");
|
||||
|
||||
b.Property<string>("PhoneNumber");
|
||||
|
||||
b.Property<bool>("PhoneNumberConfirmed");
|
||||
|
||||
b.Property<string>("SecurityStamp");
|
||||
|
||||
b.Property<bool>("TwoFactorEnabled");
|
||||
|
||||
b.Property<string>("UserName")
|
||||
.HasMaxLength(256);
|
||||
|
||||
b.Property<int>("UserType");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("NormalizedEmail")
|
||||
.HasName("EmailIndex");
|
||||
|
||||
b.HasIndex("NormalizedUserName")
|
||||
.IsUnique()
|
||||
.HasName("UserNameIndex");
|
||||
|
||||
b.ToTable("AspNetUsers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.PlexContent", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
|
@ -130,6 +313,8 @@ namespace Ombi.Store.Migrations
|
|||
|
||||
b.Property<int>("RequestedUserId");
|
||||
|
||||
b.Property<string>("Title");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ParentRequestId");
|
||||
|
@ -272,7 +457,7 @@ namespace Ombi.Store.Migrations
|
|||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Users");
|
||||
b.ToTable("OldUsers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Repository.Requests.EpisodeRequests", b =>
|
||||
|
@ -319,6 +504,51 @@ namespace Ombi.Store.Migrations
|
|||
b.ToTable("SeasonRequests");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRoleClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
|
||||
.WithMany("Claims")
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserClaim<string>", b =>
|
||||
{
|
||||
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||
.WithMany("Claims")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserLogin<string>", b =>
|
||||
{
|
||||
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||
.WithMany("Logins")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityUserRole<string>", b =>
|
||||
{
|
||||
b.HasOne("Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole")
|
||||
.WithMany("Users")
|
||||
.HasForeignKey("RoleId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("Ombi.Store.Entities.OmbiUser")
|
||||
.WithMany("Roles")
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.EmailTokens", b =>
|
||||
{
|
||||
b.HasOne("Ombi.Store.Entities.User", "User")
|
||||
.WithMany()
|
||||
.HasForeignKey("UserId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
|
||||
{
|
||||
b.HasOne("Ombi.Store.Entities.PlexContent")
|
||||
|
|
|
@ -5,10 +5,11 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="1.1.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="1.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="1.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="1.1.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
|
|
@ -45,32 +45,32 @@ namespace Ombi.Store.Repository
|
|||
|
||||
public async Task<User> GetUser(string username)
|
||||
{
|
||||
var user = await Db.Users.FirstOrDefaultAsync(x => x.Username.ToLower() == username.ToLower());
|
||||
var user = await Db.OldUsers.FirstOrDefaultAsync(x => x.Username.ToLower() == username.ToLower());
|
||||
Db.Entry(user).Reload();
|
||||
return user;
|
||||
}
|
||||
|
||||
public async Task<User> GetUser(int userId)
|
||||
{
|
||||
var user = await Db.Users.FirstOrDefaultAsync(x => x.Id == userId);
|
||||
var user = await Db.OldUsers.FirstOrDefaultAsync(x => x.Id == userId);
|
||||
Db.Entry(user).Reload();
|
||||
return user;
|
||||
}
|
||||
|
||||
public async Task CreateUser(User user)
|
||||
{
|
||||
Db.Users.Add(user);
|
||||
Db.OldUsers.Add(user);
|
||||
await Db.SaveChangesAsync();
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<User>> GetUsers()
|
||||
{
|
||||
return await Db.Users.ToListAsync();
|
||||
return await Db.OldUsers.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task DeleteUser(User user)
|
||||
{
|
||||
Db.Users.Remove(user);
|
||||
Db.OldUsers.Remove(user);
|
||||
await Db.SaveChangesAsync();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,72 +0,0 @@
|
|||
using System;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using Microsoft.AspNetCore.Authentication;
|
||||
using Microsoft.AspNetCore.Http.Authentication;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
|
||||
namespace Ombi.Auth
|
||||
{
|
||||
public class CustomJwtDataFormat : ISecureDataFormat<AuthenticationTicket>
|
||||
{
|
||||
private readonly string algorithm;
|
||||
private readonly TokenValidationParameters validationParameters;
|
||||
|
||||
public CustomJwtDataFormat(string algorithm, TokenValidationParameters validationParameters)
|
||||
{
|
||||
this.algorithm = algorithm;
|
||||
this.validationParameters = validationParameters;
|
||||
}
|
||||
|
||||
public AuthenticationTicket Unprotect(string protectedText)
|
||||
=> Unprotect(protectedText, null);
|
||||
|
||||
public AuthenticationTicket Unprotect(string protectedText, string purpose)
|
||||
{
|
||||
var handler = new JwtSecurityTokenHandler();
|
||||
ClaimsPrincipal principal = null;
|
||||
SecurityToken validToken = null;
|
||||
|
||||
try
|
||||
{
|
||||
principal = handler.ValidateToken(protectedText, this.validationParameters, out validToken);
|
||||
|
||||
var validJwt = validToken as JwtSecurityToken;
|
||||
|
||||
if (validJwt == null)
|
||||
{
|
||||
throw new ArgumentException("Invalid JWT");
|
||||
}
|
||||
|
||||
if (!validJwt.Header.Alg.Equals(algorithm, StringComparison.Ordinal))
|
||||
{
|
||||
throw new ArgumentException($"Algorithm must be '{algorithm}'");
|
||||
}
|
||||
|
||||
// Additional custom validation of JWT claims here (if any)
|
||||
}
|
||||
catch (SecurityTokenValidationException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
catch (ArgumentException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Validation passed. Return a valid AuthenticationTicket:
|
||||
return new AuthenticationTicket(principal, new AuthenticationProperties(), "Cookie");
|
||||
}
|
||||
|
||||
// This ISecureDataFormat implementation is decode-only
|
||||
public string Protect(AuthenticationTicket data)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public string Protect(AuthenticationTicket data, string purpose)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
namespace Ombi.Auth
|
||||
{
|
||||
public class TokenAuthenticationOptions
|
||||
{
|
||||
public string SecretKey { get; set; }
|
||||
public string Issuer { get; set; }
|
||||
public string Audience { get; set; }
|
||||
public string TokenPath { get; set; }
|
||||
public string CookieName { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,161 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json;
|
||||
using Ombi.Core.IdentityResolver;
|
||||
using Ombi.Models;
|
||||
using Ombi.Store.Context;
|
||||
using Ombi.Store.Repository;
|
||||
|
||||
namespace Ombi.Auth
|
||||
{
|
||||
public class TokenProviderMiddleware
|
||||
{
|
||||
private readonly RequestDelegate _next;
|
||||
private readonly TokenProviderOptions _options;
|
||||
private readonly JsonSerializerSettings _serializerSettings;
|
||||
private readonly IUserIdentityManager _identityManager;
|
||||
|
||||
public TokenProviderMiddleware(
|
||||
RequestDelegate next,
|
||||
IOptions<TokenProviderOptions> options, IUserIdentityManager manager)
|
||||
{
|
||||
_next = next;
|
||||
_options = options.Value;
|
||||
ThrowIfInvalidOptions(_options);
|
||||
|
||||
_serializerSettings = new JsonSerializerSettings
|
||||
{
|
||||
Formatting = Formatting.Indented
|
||||
};
|
||||
_identityManager = manager;
|
||||
}
|
||||
|
||||
public Task Invoke(HttpContext context)
|
||||
{
|
||||
// If the request path doesn't match, skip
|
||||
if (!context.Request.Path.Equals(_options.Path, StringComparison.Ordinal))
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
return _next(context);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
// Request must be POST with Content-Type: application/json
|
||||
if (!context.Request.Method.Equals("POST")
|
||||
)
|
||||
{
|
||||
context.Response.StatusCode = 400;
|
||||
return context.Response.WriteAsync("Bad request.");
|
||||
}
|
||||
|
||||
|
||||
return GenerateToken(context);
|
||||
}
|
||||
|
||||
private async Task GenerateToken(HttpContext context)
|
||||
{
|
||||
var request = context.Request;
|
||||
UserAuthModel userInfo;
|
||||
|
||||
using (var bodyReader = new StreamReader(request.Body))
|
||||
{
|
||||
string body = await bodyReader.ReadToEndAsync();
|
||||
userInfo = JsonConvert.DeserializeObject<UserAuthModel>(body);
|
||||
}
|
||||
|
||||
var identity = await _options.IdentityResolver(userInfo.Username, userInfo.Password, _identityManager);
|
||||
if (identity == null)
|
||||
{
|
||||
context.Response.StatusCode = 400;
|
||||
await context.Response.WriteAsync("Invalid username or password.");
|
||||
return;
|
||||
}
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
// Specifically add the jti (nonce), iat (issued timestamp), and sub (subject/user) claims.
|
||||
// You can add other claims here, if you want:
|
||||
var jwtClaims = new List<Claim>
|
||||
{
|
||||
new Claim(JwtRegisteredClaimNames.Sub, userInfo.Username),
|
||||
new Claim(JwtRegisteredClaimNames.Jti, await _options.NonceGenerator()),
|
||||
new Claim(JwtRegisteredClaimNames.Iat, new DateTimeOffset(now).ToUniversalTime().ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64)
|
||||
};
|
||||
|
||||
identity.Claims.ToList().AddRange(jwtClaims);
|
||||
|
||||
// Create the JWT and write it to a string
|
||||
var jwt = new JwtSecurityToken(
|
||||
issuer: _options.Issuer,
|
||||
audience: _options.Audience,
|
||||
claims: identity.Claims,
|
||||
notBefore: now,
|
||||
expires: now.Add(_options.Expiration),
|
||||
signingCredentials: _options.SigningCredentials);
|
||||
var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);
|
||||
|
||||
var response = new
|
||||
{
|
||||
access_token = encodedJwt,
|
||||
expires_in = (int)_options.Expiration.TotalSeconds
|
||||
};
|
||||
|
||||
// Serialize and return the response
|
||||
context.Response.ContentType = "application/json";
|
||||
await context.Response.WriteAsync(JsonConvert.SerializeObject(response, _serializerSettings));
|
||||
}
|
||||
|
||||
private static void ThrowIfInvalidOptions(TokenProviderOptions options)
|
||||
{
|
||||
if (string.IsNullOrEmpty(options.Path))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(TokenProviderOptions.Path));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(options.Issuer))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(TokenProviderOptions.Issuer));
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(options.Audience))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(TokenProviderOptions.Audience));
|
||||
}
|
||||
|
||||
if (options.Expiration == TimeSpan.Zero)
|
||||
{
|
||||
throw new ArgumentException("Must be a non-zero TimeSpan.", nameof(TokenProviderOptions.Expiration));
|
||||
}
|
||||
|
||||
if (options.IdentityResolver == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(TokenProviderOptions.IdentityResolver));
|
||||
}
|
||||
|
||||
if (options.SigningCredentials == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(TokenProviderOptions.SigningCredentials));
|
||||
}
|
||||
|
||||
if (options.NonceGenerator == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(TokenProviderOptions.NonceGenerator));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Cryptography;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Ombi.Core.IdentityResolver;
|
||||
|
||||
namespace Ombi.Auth
|
||||
{
|
||||
public class TokenProviderOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// The relative request path to listen on.
|
||||
/// </summary>
|
||||
/// <remarks>The default path is <c>/token</c>.</remarks>
|
||||
public string Path { get; set; } = "/token/";
|
||||
|
||||
/// <summary>
|
||||
/// The Issuer (iss) claim for generated tokens.
|
||||
/// </summary>
|
||||
public string Issuer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Audience (aud) claim for the generated tokens.
|
||||
/// </summary>
|
||||
public string Audience { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The expiration time for the generated tokens.
|
||||
/// </summary>
|
||||
/// <remarks>The default is 1 Days.</remarks>
|
||||
public TimeSpan Expiration { get; set; } = TimeSpan.FromDays(1);
|
||||
|
||||
/// <summary>
|
||||
/// The signing key to use when generating tokens.
|
||||
/// </summary>
|
||||
public SigningCredentials SigningCredentials { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Resolves a user identity given a username and password.
|
||||
/// </summary>
|
||||
public Func<string, string, IUserIdentityManager, Task<ClaimsIdentity>> IdentityResolver { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Generates a random value (nonce) for each generated token.
|
||||
/// </summary>
|
||||
/// <remarks>The default nonce is a random GUID.</remarks>
|
||||
public Func<Task<string>> NonceGenerator { get; set; }
|
||||
= () => Task.FromResult(Guid.NewGuid().ToString());
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Rx';
|
||||
|
||||
import { ServiceHelpers } from '../services/service.helpers';
|
||||
|
@ -8,18 +7,28 @@ import { IUserLogin, ILocalUser } from './IUserLogin';
|
|||
|
||||
import { tokenNotExpired, JwtHelper } from 'angular2-jwt';
|
||||
|
||||
import { Http } from '@angular/http';
|
||||
import { Http, Headers, URLSearchParams } from '@angular/http';
|
||||
|
||||
@Injectable()
|
||||
export class AuthService extends ServiceHelpers {
|
||||
constructor(http: Http) {
|
||||
super(http, '/api/v1/token');
|
||||
super(http, '/connect/token');
|
||||
}
|
||||
|
||||
jwtHelper: JwtHelper = new JwtHelper();
|
||||
|
||||
login(login:IUserLogin) : Observable<any> {
|
||||
return this.http.post(`${this.url}/`, JSON.stringify(login), { headers: this.headers })
|
||||
login(login: IUserLogin): Observable<any> {
|
||||
this.headers = new Headers();
|
||||
this.headers.append('Content-Type', 'application/x-www-form-urlencoded');
|
||||
let data = new URLSearchParams();
|
||||
data.append('client_id', 'frontend');
|
||||
data.append('scope', 'api');
|
||||
data.append('client_secret', 'secret');
|
||||
data.append('grant_type', 'password');
|
||||
data.append('username', login.username);
|
||||
data.append('password', login.password);
|
||||
|
||||
return this.http.post(`${this.url}/`, data.toString(), { headers: this.headers })
|
||||
.map(this.extractData);
|
||||
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
<div *ngIf="childRequests">
|
||||
<div *ngFor="let child of childRequests">
|
||||
|
||||
<div class="col-md-12">
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
8
src/Ombi/Config/UserSettings.cs
Normal file
8
src/Ombi/Config/UserSettings.cs
Normal file
|
@ -0,0 +1,8 @@
|
|||
namespace Ombi.Config
|
||||
{
|
||||
public class UserSettings
|
||||
{
|
||||
public string WebsiteUrl { get; set; }
|
||||
public bool UseHttps { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,18 +1,18 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Security.Claims;
|
||||
using System.Threading.Tasks;
|
||||
using AutoMapper;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Ombi.Attributes;
|
||||
using Ombi.Core.Claims;
|
||||
using Ombi.Core.IdentityResolver;
|
||||
using Ombi.Core.Models;
|
||||
using Ombi.Core.Models.UI;
|
||||
using Ombi.Models;
|
||||
using Ombi.Store.Entities;
|
||||
|
||||
namespace Ombi.Controllers
|
||||
{
|
||||
|
@ -23,13 +23,15 @@ namespace Ombi.Controllers
|
|||
[PowerUser]
|
||||
public class IdentityController : BaseV1ApiController
|
||||
{
|
||||
public IdentityController(IUserIdentityManager identity, IMapper mapper)
|
||||
public IdentityController(UserManager<OmbiUser> user, IMapper mapper, RoleManager<IdentityRole> rm)
|
||||
{
|
||||
IdentityManager = identity;
|
||||
UserManager = user;
|
||||
Mapper = mapper;
|
||||
RoleManager = rm;
|
||||
}
|
||||
|
||||
private IUserIdentityManager IdentityManager { get; }
|
||||
private UserManager<OmbiUser> UserManager { get; }
|
||||
private RoleManager<IdentityRole> RoleManager { get; }
|
||||
private IMapper Mapper { get; }
|
||||
|
||||
/// <summary>
|
||||
|
@ -39,10 +41,9 @@ namespace Ombi.Controllers
|
|||
[HttpGet]
|
||||
public async Task<UserViewModel> GetUser()
|
||||
{
|
||||
return Mapper.Map<UserViewModel>(await IdentityManager.GetUser(this.HttpContext.User.Identity.Name));
|
||||
return Mapper.Map<UserViewModel>(await UserManager.GetUserAsync(User));
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This is what the Wizard will call when creating the user for the very first time.
|
||||
/// This should never be called after this.
|
||||
|
@ -57,20 +58,39 @@ namespace Ombi.Controllers
|
|||
[AllowAnonymous]
|
||||
public async Task<bool> CreateWizardUser([FromBody] UserAuthModel user)
|
||||
{
|
||||
var users = await IdentityManager.GetUsers();
|
||||
var users = UserManager.Users;
|
||||
if (users.Any())
|
||||
{
|
||||
// No one should be calling this. Only the wizard
|
||||
return false;
|
||||
}
|
||||
|
||||
await IdentityManager.CreateUser(new UserDto
|
||||
var userToCreate = new OmbiUser
|
||||
{
|
||||
Username = user.Username,
|
||||
UserType = UserType.LocalUser,
|
||||
Claims = new List<Claim>() { new Claim(ClaimTypes.Role, OmbiClaims.Admin) },
|
||||
Password = user.Password,
|
||||
});
|
||||
UserName = user.Username,
|
||||
|
||||
};
|
||||
|
||||
var result = await UserManager.CreateAsync(userToCreate, user.Password);
|
||||
if (result.Succeeded)
|
||||
{
|
||||
if (!(await RoleManager.RoleExistsAsync("Admin")))
|
||||
{
|
||||
var r = await RoleManager.CreateAsync(new IdentityRole("Admin"));
|
||||
}
|
||||
var re = await UserManager.AddToRoleAsync(userToCreate, "Admin");
|
||||
|
||||
var v = User.IsInRole("Admin");
|
||||
|
||||
|
||||
}
|
||||
//await UserManager.CreateUser(new UserDto
|
||||
//{
|
||||
// Username = user.Username,
|
||||
// UserType = UserType.LocalUser,
|
||||
// Claims = new List<Claim>() { new Claim(ClaimTypes.Role, OmbiClaims.Admin) },
|
||||
// Password = user.Password,
|
||||
//});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -88,7 +108,7 @@ namespace Ombi.Controllers
|
|||
|
||||
var fields = fieldInfos.Where(fi => fi.IsLiteral && !fi.IsInitOnly).ToList();
|
||||
var allClaims = fields.Select(x => x.Name).ToList();
|
||||
var users = Mapper.Map<IEnumerable<UserViewModel>>(await IdentityManager.GetUsers()).ToList();
|
||||
var users = Mapper.Map<IEnumerable<UserViewModel>>(UserManager.Users).ToList();
|
||||
|
||||
foreach (var user in users)
|
||||
{
|
||||
|
@ -121,7 +141,7 @@ namespace Ombi.Controllers
|
|||
|
||||
var fields = fieldInfos.Where(fi => fi.IsLiteral && !fi.IsInitOnly).ToList();
|
||||
var allClaims = fields.Select(x => x.Name).ToList();
|
||||
var user = Mapper.Map<UserViewModel>(await IdentityManager.GetUser(id));
|
||||
var user = Mapper.Map<UserViewModel>(await UserManager.Users.FirstOrDefaultAsync(x => x.Id == id.ToString()));
|
||||
|
||||
|
||||
var userClaims = user.Claims.Select(x => x.Value);
|
||||
|
@ -145,37 +165,37 @@ namespace Ombi.Controllers
|
|||
/// </summary>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <returns></returns>
|
||||
[HttpPost]
|
||||
public async Task<UserViewModel> CreateUser([FromBody] UserViewModel user)
|
||||
{
|
||||
user.Id = null;
|
||||
var userResult = await IdentityManager.CreateUser(Mapper.Map<UserDto>(user));
|
||||
return Mapper.Map<UserViewModel>(userResult);
|
||||
}
|
||||
|
||||
//[HttpPost]
|
||||
//public async Task<UserViewModel> CreateUser([FromBody] UserViewModel user)
|
||||
//{
|
||||
// user.Id = null;
|
||||
// var userResult = await UserManager.CreateUser(Mapper.Map<UserDto>(user));
|
||||
// return Mapper.Map<UserViewModel>(userResult);
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the user.
|
||||
/// </summary>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <returns></returns>
|
||||
[HttpPut]
|
||||
public async Task<UserViewModel> UpdateUser([FromBody] UserViewModel user)
|
||||
{
|
||||
var userResult = await IdentityManager.UpdateUser(Mapper.Map<UserDto>(user));
|
||||
return Mapper.Map<UserViewModel>(userResult);
|
||||
}
|
||||
//[HttpPut]
|
||||
//public async Task<UserViewModel> UpdateUser([FromBody] UserViewModel user)
|
||||
//{
|
||||
// var userResult = await UserManager.UpdateUser(Mapper.Map<UserDto>(user));
|
||||
// return Mapper.Map<UserViewModel>(userResult);
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the user.
|
||||
/// </summary>
|
||||
/// <param name="user">The user.</param>
|
||||
/// <returns></returns>
|
||||
[HttpDelete]
|
||||
public async Task<StatusCodeResult> DeleteUser([FromBody] UserViewModel user)
|
||||
{
|
||||
await IdentityManager.DeleteUser(Mapper.Map<UserDto>(user));
|
||||
return Ok();
|
||||
}
|
||||
///// <summary>
|
||||
///// Deletes the user.
|
||||
///// </summary>
|
||||
///// <param name="user">The user.</param>
|
||||
///// <returns></returns>
|
||||
//[HttpDelete]
|
||||
//public async Task<StatusCodeResult> DeleteUser([FromBody] UserViewModel user)
|
||||
//{
|
||||
// await UserManager.DeleteUser(Mapper.Map<UserDto>(user));
|
||||
// return Ok();
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all available claims in the system.
|
||||
|
|
58
src/Ombi/IdentityConfig.cs
Normal file
58
src/Ombi/IdentityConfig.cs
Normal file
|
@ -0,0 +1,58 @@
|
|||
using System.Collections.Generic;
|
||||
using IdentityServer4.Models;
|
||||
|
||||
namespace Ombi
|
||||
{
|
||||
public class IdentityConfig
|
||||
{
|
||||
// scopes define the resources in your system
|
||||
public static IEnumerable<IdentityResource> GetIdentityResources()
|
||||
{
|
||||
return new List<IdentityResource>
|
||||
{
|
||||
new IdentityResources.OpenId(),
|
||||
new IdentityResources.Profile(),
|
||||
new IdentityResource {
|
||||
Name = "role",
|
||||
UserClaims = new List<string> {"role"}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static IEnumerable<ApiResource> GetApiResources()
|
||||
{
|
||||
return new List<ApiResource>
|
||||
{
|
||||
new ApiResource("api", "API")
|
||||
{
|
||||
UserClaims = {"role", "name"},
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// clients want to access resources (aka scopes)
|
||||
public static IEnumerable<Client> GetClients()
|
||||
{
|
||||
// client credentials client
|
||||
return new List<Client>
|
||||
{
|
||||
new Client
|
||||
{
|
||||
ClientId = "frontend",
|
||||
AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
|
||||
|
||||
ClientSecrets =
|
||||
{
|
||||
new Secret("secret".Sha256()) // TODO read up on what this actually is
|
||||
},
|
||||
AllowedScopes =
|
||||
{
|
||||
"api",
|
||||
},
|
||||
AccessTokenType = AccessTokenType.Jwt
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -45,18 +45,21 @@
|
|||
<PackageReference Include="Hangfire.MemoryStorage.Core" Version="1.4.0" />
|
||||
<PackageReference Include="Hangfire.RecurringJobExtensions" Version="1.1.6" />
|
||||
<PackageReference Include="Hangfire.SQLite.Core" Version="1.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.2" />
|
||||
<PackageReference Include="IdentityServer4" Version="1.5.2" />
|
||||
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="1.2.1" />
|
||||
<PackageReference Include="IdentityServer4.AspNetIdentity" Version="1.0.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="1.1.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="1.1.3" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.1" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="1.1.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="1.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="1.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="1.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Design" Version="1.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="1.1.2" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer.Design" Version="1.1.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="1.1.2" />
|
||||
<PackageReference Include="Microsoft.VisualStudio.Web.BrowserLink" Version="1.1.2" />
|
||||
<PackageReference Include="MiniProfiler.AspNetCore.Mvc" Version="4.0.0-alpha6-79" />
|
||||
<PackageReference Include="Serilog" Version="2.4.0" />
|
||||
<PackageReference Include="Serilog.Extensions.Logging" Version="1.4.0" />
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
using System;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Ombi.Auth;
|
||||
using Ombi.Core.IdentityResolver;
|
||||
|
||||
namespace Ombi
|
||||
{
|
||||
public partial class Startup
|
||||
{
|
||||
/// <summary>
|
||||
/// A key...
|
||||
/// </summary>
|
||||
public SymmetricSecurityKey SigningKey;
|
||||
private void ConfigureAuth(IApplicationBuilder app, IOptions<TokenAuthenticationOptions> options)
|
||||
{
|
||||
|
||||
var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(options.Value.SecretKey));
|
||||
|
||||
var tokenProviderOptions = new TokenProviderOptions
|
||||
{
|
||||
Path = options.Value.TokenPath,
|
||||
Audience = options.Value.Audience,
|
||||
Issuer = options.Value.Issuer,
|
||||
SigningCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256),
|
||||
IdentityResolver = GetIdentity
|
||||
};
|
||||
|
||||
var tokenValidationParameters = new TokenValidationParameters
|
||||
{
|
||||
// The signing key must match!
|
||||
ValidateIssuerSigningKey = true,
|
||||
IssuerSigningKey = signingKey,
|
||||
// Validate the JWT Issuer (iss) claim
|
||||
ValidateIssuer = true,
|
||||
ValidIssuer = options.Value.Issuer,
|
||||
// Validate the JWT Audience (aud) claim
|
||||
ValidateAudience = true,
|
||||
ValidAudience = options.Value.Audience,
|
||||
// Validate the token expiry
|
||||
ValidateLifetime = true,
|
||||
// If you want to allow a certain amount of clock drift, set that here:
|
||||
ClockSkew = TimeSpan.Zero,
|
||||
};
|
||||
|
||||
app.UseJwtBearerAuthentication(new JwtBearerOptions
|
||||
{
|
||||
AutomaticAuthenticate = true,
|
||||
AutomaticChallenge = true,
|
||||
TokenValidationParameters = tokenValidationParameters,
|
||||
});
|
||||
|
||||
app.UseMiddleware<TokenProviderMiddleware>(Options.Create(tokenProviderOptions));
|
||||
}
|
||||
|
||||
|
||||
private async Task<ClaimsIdentity> GetIdentity(string username, string password, IUserIdentityManager userIdentityManager)
|
||||
{
|
||||
var validLogin = await userIdentityManager.CredentialsValid(username, password);
|
||||
if (!validLogin)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var user = await userIdentityManager.GetUser(username);
|
||||
var claim = new ClaimsIdentity(new GenericIdentity(user.Username, "Token"), user.Claims);
|
||||
return claim;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,19 +9,23 @@ using Hangfire.SQLite;
|
|||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.AspNetCore.SpaServices.Webpack;
|
||||
using Microsoft.AspNetCore.StaticFiles;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
using Ombi.Auth;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Ombi.Config;
|
||||
using Ombi.DependencyInjection;
|
||||
using Ombi.Mapping;
|
||||
using Ombi.Schedule;
|
||||
using Ombi.Store.Context;
|
||||
using Ombi.Store.Entities;
|
||||
using Serilog;
|
||||
using Serilog.Events;
|
||||
using StackExchange.Profiling;
|
||||
|
@ -66,9 +70,35 @@ namespace Ombi
|
|||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
// Add framework services.
|
||||
services.AddDbContext<OmbiContext>(options =>
|
||||
options.UseSqlite("Data Source=Ombi.db"));
|
||||
|
||||
services.AddIdentity<OmbiUser, IdentityRole>()
|
||||
.AddEntityFrameworkStores<OmbiContext>()
|
||||
.AddDefaultTokenProviders();
|
||||
|
||||
services.AddIdentityServer()
|
||||
.AddTemporarySigningCredential()
|
||||
.AddInMemoryPersistedGrants()
|
||||
.AddInMemoryIdentityResources(IdentityConfig.GetIdentityResources())
|
||||
.AddInMemoryApiResources(IdentityConfig.GetApiResources())
|
||||
.AddInMemoryClients(IdentityConfig.GetClients())
|
||||
.AddAspNetIdentity<OmbiUser>();
|
||||
|
||||
services.Configure<IdentityOptions>(options =>
|
||||
{
|
||||
options.Password.RequireDigit = false;
|
||||
options.Password.RequiredLength = 1;
|
||||
options.Password.RequireLowercase = false;
|
||||
options.Password.RequireNonAlphanumeric = false;
|
||||
options.Password.RequireUppercase = false;
|
||||
});
|
||||
|
||||
services.AddMemoryCache();
|
||||
|
||||
services.AddMvc()
|
||||
.AddJsonOptions(x => x.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
|
||||
|
||||
services.AddOmbiMappingProfile();
|
||||
services.AddAutoMapper(expression =>
|
||||
{
|
||||
|
@ -114,8 +144,9 @@ namespace Ombi
|
|||
services.AddScoped<IPrincipal>(sp => sp.GetService<IHttpContextAccessor>().HttpContext.User);
|
||||
|
||||
|
||||
services.Configure<TokenAuthenticationOptions>(Configuration.GetSection("TokenAuthentication"));
|
||||
//services.Configure<TokenAuthenticationOptions>(Configuration.GetSection("TokenAuthentication"));
|
||||
services.Configure<ApplicationSettings>(Configuration.GetSection("ApplicationSettings"));
|
||||
services.Configure<UserSettings>(Configuration.GetSection("UserSettings"));
|
||||
|
||||
services.AddHangfire(x =>
|
||||
{
|
||||
|
@ -140,6 +171,24 @@ namespace Ombi
|
|||
{
|
||||
//loggerFactory.AddConsole(Configuration.GetSection("Logging"));
|
||||
//loggerFactory.AddDebug();
|
||||
var options = (IOptions<UserSettings>) app.ApplicationServices.GetService(
|
||||
typeof(IOptions<UserSettings>));
|
||||
|
||||
app.UseIdentity();
|
||||
app.UseIdentityServer();
|
||||
app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
|
||||
{
|
||||
Authority = options.Value.WebsiteUrl,
|
||||
ApiName = "api",
|
||||
ApiSecret = "secret",
|
||||
|
||||
EnableCaching = true,
|
||||
CacheDuration = TimeSpan.FromMinutes(10), // that's the default
|
||||
RequireHttpsMetadata = options.Value.UseHttps, // FOR DEV set to false
|
||||
AutomaticAuthenticate = true,
|
||||
AutomaticChallenge = true
|
||||
|
||||
});
|
||||
|
||||
loggerFactory.AddSerilog();
|
||||
|
||||
|
@ -180,7 +229,7 @@ namespace Ombi
|
|||
var jobSetup = (IJobSetup)app.ApplicationServices.GetService(typeof(IJobSetup));
|
||||
jobSetup.Setup();
|
||||
|
||||
ConfigureAuth(app, (IOptions<TokenAuthenticationOptions>)app.ApplicationServices.GetService(typeof(IOptions<TokenAuthenticationOptions>)));
|
||||
//ConfigureAuth(app, (IOptions<TokenAuthenticationOptions>)app.ApplicationServices.GetService(typeof(IOptions<TokenAuthenticationOptions>)));
|
||||
|
||||
var provider = new FileExtensionContentTypeProvider();
|
||||
provider.Mappings[".map"] = "application/octet-stream";
|
||||
|
|
|
@ -8,6 +8,10 @@
|
|||
"ApplicationSettings": {
|
||||
"Verison": "{{VERSIONNUMBER}}"
|
||||
},
|
||||
"UserSettings": {
|
||||
"WebsiteUrl": "http://localhost:52038",
|
||||
"UseHttps": false
|
||||
},
|
||||
"TokenAuthentication": {
|
||||
"SecretKey": "secretkey_secretkey123!",
|
||||
"Issuer": "OmbiIssuer",
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
{
|
||||
"name": "ombi",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"PACE": "pace#^1.0.2",
|
||||
"font-awesome": "^4.7.0"
|
||||
}
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue