Compare commits

..

No commits in common. "d1408ce6a46357417d3b54395e0c447290ffe10d" and "7c88967f7f2101c2657c18507c94034136f83530" have entirely different histories.

14 changed files with 40 additions and 71 deletions

View File

@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Newsbot.Collector.Api.Domain.Consts; using Newsbot.Collector.Api.Domain;
using Newsbot.Collector.Domain.Models.Config; using Newsbot.Collector.Domain.Models.Config;
using Newsbot.Collector.Services.Jobs; using Newsbot.Collector.Services.Jobs;

View File

@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Newsbot.Collector.Api.Domain.Consts; using Newsbot.Collector.Api.Domain;
using Newsbot.Collector.Domain.Requests; using Newsbot.Collector.Domain.Requests;
using Newsbot.Collector.Domain.Response; using Newsbot.Collector.Domain.Response;
using Newsbot.Collector.Domain.Results; using Newsbot.Collector.Domain.Results;

View File

@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Newsbot.Collector.Api.Domain.Consts; using Newsbot.Collector.Api.Domain;
using Newsbot.Collector.Domain.Models.Config; using Newsbot.Collector.Domain.Models.Config;
using Newsbot.Collector.Domain.Models.Config.Sources; using Newsbot.Collector.Domain.Models.Config.Sources;
using Newsbot.Collector.Services.Jobs; using Newsbot.Collector.Services.Jobs;

View File

@ -1,14 +1,17 @@
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Newsbot.Collector.Api.Domain.Consts; using Microsoft.Extensions.Options;
using Newsbot.Collector.Api.Domain;
using Newsbot.Collector.Database.Repositories;
using Newsbot.Collector.Domain.Consts; using Newsbot.Collector.Domain.Consts;
using Newsbot.Collector.Domain.Dto; using Newsbot.Collector.Domain.Dto;
using Newsbot.Collector.Domain.Entities; using Newsbot.Collector.Domain.Entities;
using Newsbot.Collector.Domain.Interfaces; using Newsbot.Collector.Domain.Interfaces;
using Newsbot.Collector.Domain.Models;
using Newsbot.Collector.Services.HtmlParser; using Newsbot.Collector.Services.HtmlParser;
namespace Newsbot.Collector.Api.Controllers.v1; namespace Newsbot.Collector.Api.Controllers;
[ApiController] [ApiController]
[Route("api/sources")] [Route("api/sources")]

View File

@ -3,10 +3,11 @@ using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Newsbot.Collector.Api.Domain.Consts; using Newsbot.Collector.Api.Domain;
using Newsbot.Collector.Domain.Models.Config; using Newsbot.Collector.Domain.Models.Config;
using Newsbot.Collector.Domain.Models.Config.Sources; using Newsbot.Collector.Domain.Models.Config.Sources;
using Newsbot.Collector.Services.Jobs; using Newsbot.Collector.Services.Jobs;
using ILogger = Grpc.Core.Logging.ILogger;
namespace Newsbot.Collector.Api.Controllers.v1; namespace Newsbot.Collector.Api.Controllers.v1;

View File

@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Newsbot.Collector.Api.Domain.Consts; using Newsbot.Collector.Api.Domain;
using Newsbot.Collector.Database; using Newsbot.Collector.Database;
using Newsbot.Collector.Database.Repositories; using Newsbot.Collector.Database.Repositories;
using Newsbot.Collector.Domain.Interfaces; using Newsbot.Collector.Domain.Interfaces;

View File

@ -1,7 +1,7 @@
using System.Text; using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using Newsbot.Collector.Api.Domain.Consts; using Newsbot.Collector.Api.Domain;
using Newsbot.Collector.Domain.Models.Config; using Newsbot.Collector.Domain.Models.Config;
namespace Newsbot.Collector.Api.Startup; namespace Newsbot.Collector.Api.Startup;
@ -44,9 +44,7 @@ public static class IdentityStartup
services.AddAuthorization(options => services.AddAuthorization(options =>
{ {
options.AddPolicy(Authorization.AdministratorPolicy, options.AddPolicy(Authorization.AdministratorPolicy,
b => b.RequireRole(Authorization.AdministratorsRole, "true")); b => b.RequireClaim(Authorization.AdministratorClaim, "true"));
options.AddPolicy(Authorization.UserPolicy,
b => b.RequireRole(Authorization.UsersRole, "true"));
}); });
} }
} }

View File

@ -1,13 +1,17 @@
using Microsoft.EntityFrameworkCore; using System.Data;
using Dapper;
using Microsoft.Extensions.Configuration;
using Newsbot.Collector.Domain.Entities; using Newsbot.Collector.Domain.Entities;
using Newsbot.Collector.Domain.Interfaces; using Newsbot.Collector.Domain.Interfaces;
using Newsbot.Collector.Domain.Models;
using Npgsql;
namespace Newsbot.Collector.Database.Repositories; namespace Newsbot.Collector.Database.Repositories;
public class SourcesTable : ISourcesRepository public class SourcesTable : ISourcesRepository
{ {
//private readonly string _connectionString; //private readonly string _connectionString;
private readonly DatabaseContext _context; private DatabaseContext _context;
public SourcesTable(string connectionString) public SourcesTable(string connectionString)
{ {
@ -110,14 +114,6 @@ public class SourcesTable : ISourcesRepository
return res; return res;
} }
public async Task<int> TotalByTypeAsync(string type)
{
var res = await _context.Sources
.Where(f => f.Type == type )
.CountAsync();
return res;
}
public int Disable(Guid id) public int Disable(Guid id)
{ {
//using var context = new DatabaseContext(_connectionString); //using var context = new DatabaseContext(_connectionString);

View File

@ -1,13 +1,12 @@
namespace Newsbot.Collector.Api.Domain.Consts; namespace Newsbot.Collector.Api.Domain;
public static class Authorization public static class Authorization
{ {
public const string AdministratorPolicy = "Administrator"; public const string AdministratorPolicy = "Administrator";
public const string AdministratorsRole = AdministratorPolicy;
public const string AdministratorClaim = "administrator"; public const string AdministratorClaim = "administrator";
public const string AdministratorsRole = AdministratorPolicy;
public const string UserPolicy = "User"; public const string UserPolicy = "User";
public const string UsersRole = UserPolicy; public const string UsersRole = UserPolicy;
public const string UserClaim = "user";
} }

View File

@ -14,7 +14,6 @@ public interface ISourcesRepository
public List<SourceEntity> List(int page, int count); public List<SourceEntity> List(int page, int count);
public List<SourceEntity> ListBySource(string source,int page, int limit); public List<SourceEntity> ListBySource(string source,int page, int limit);
public List<SourceEntity> ListByType(string type,int page, int limit = 25); public List<SourceEntity> ListByType(string type,int page, int limit = 25);
public Task<int> TotalByTypeAsync(string type);
public int Disable(Guid id); public int Disable(Guid id);
public int Enable(Guid id); public int Enable(Guid id);
public void Delete(Guid id); public void Delete(Guid id);

View File

@ -3,7 +3,6 @@ using System.Security.Claims;
using System.Text; using System.Text;
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using Newsbot.Collector.Api.Domain.Consts;
using Newsbot.Collector.Domain.Results; using Newsbot.Collector.Domain.Results;
using Newsbot.Collector.Domain.Entities; using Newsbot.Collector.Domain.Entities;
using Newsbot.Collector.Domain.Interfaces; using Newsbot.Collector.Domain.Interfaces;
@ -17,24 +16,22 @@ public interface IIdentityService
AuthenticationResult Register(string email, string password); AuthenticationResult Register(string email, string password);
AuthenticationResult Login(string email, string password); AuthenticationResult Login(string email, string password);
AuthenticationResult RefreshToken(string token, string refreshToken); AuthenticationResult RefreshToken(string token, string refreshToken);
void AddRole(string name, string userId); void AddRole(string roleName, string userId);
} }
public class IdentityService : IIdentityService public class IdentityService : IIdentityService
{ {
private readonly UserManager<IdentityUser> _userManager; private readonly UserManager<IdentityUser> _userManager;
private readonly RoleManager<IdentityRole> _roleManager;
private readonly JwtSettings _jwtSettings; private readonly JwtSettings _jwtSettings;
private readonly TokenValidationParameters _tokenValidationParameters; private readonly TokenValidationParameters _tokenValidationParameters;
private readonly IRefreshTokenRepository _refreshTokenRepository; private readonly IRefreshTokenRepository _refreshTokenRepository;
public IdentityService(UserManager<IdentityUser> userManager, JwtSettings jwtSettings, TokenValidationParameters tokenValidationParameters, IRefreshTokenRepository refreshTokenRepository, RoleManager<IdentityRole> roleManager) public IdentityService(UserManager<IdentityUser> userManager, JwtSettings jwtSettings, TokenValidationParameters tokenValidationParameters, IRefreshTokenRepository refreshTokenRepository)
{ {
_userManager = userManager; _userManager = userManager;
_jwtSettings = jwtSettings; _jwtSettings = jwtSettings;
_tokenValidationParameters = tokenValidationParameters; _tokenValidationParameters = tokenValidationParameters;
_refreshTokenRepository = refreshTokenRepository; _refreshTokenRepository = refreshTokenRepository;
_roleManager = roleManager;
} }
public AuthenticationResult Register(string email, string password) public AuthenticationResult Register(string email, string password)
@ -67,10 +64,7 @@ public class IdentityService : IIdentityService
}; };
} }
var addRole = _userManager.AddToRoleAsync(newUser, Authorization.UsersRole); return GenerateJwtToken(newUser);
addRole.Wait();
return GenerateJwtToken(newUser);
} }
public AuthenticationResult Login(string email, string password) public AuthenticationResult Login(string email, string password)
@ -115,9 +109,8 @@ public class IdentityService : IIdentityService
var expiryDateUnix = long.Parse(validatedToken.Claims.Single(x => x.Type == JwtRegisteredClaimNames.Exp).Value); var expiryDateUnix = long.Parse(validatedToken.Claims.Single(x => x.Type == JwtRegisteredClaimNames.Exp).Value);
// generate the unix epoc, add expiry time // generate the unix epoc, add expiry time
var expiryDateTimeUtc = new DateTime(1970, 0, 0, 0, 0, 0, DateTimeKind.Utc)
var unixTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); .AddSeconds(expiryDateUnix);
var expiryDateTimeUtc = unixTime.AddSeconds(expiryDateUnix);
// if it expires in the future // if it expires in the future
if (expiryDateTimeUtc > DateTime.Now) if (expiryDateTimeUtc > DateTime.Now)
@ -186,7 +179,7 @@ public class IdentityService : IIdentityService
return GenerateJwtToken(user.Result); return GenerateJwtToken(user.Result);
} }
public void AddRole(string name, string userId) public void AddRole(string roleName, string userId)
{ {
var user = _userManager.FindByIdAsync(userId); var user = _userManager.FindByIdAsync(userId);
user.Wait(); user.Wait();
@ -196,14 +189,7 @@ public class IdentityService : IIdentityService
throw new Exception("User was not found"); throw new Exception("User was not found");
} }
if (!name.Equals(Authorization.AdministratorClaim) _userManager.AddToRoleAsync(user.Result, roleName);
|| !name.Equals(Authorization.UserClaim))
{
throw new Exception("Invalid role");
}
var addRole = _userManager.AddToRoleAsync(user.Result, name);
addRole.Wait();
} }
private ClaimsPrincipal? CheckTokenSigner(string token) private ClaimsPrincipal? CheckTokenSigner(string token)
@ -235,25 +221,15 @@ public class IdentityService : IIdentityService
{ {
var tokenHandler = new JwtSecurityTokenHandler(); var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_jwtSettings.Secret ?? ""); var key = Encoding.ASCII.GetBytes(_jwtSettings.Secret ?? "");
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Sub, user.Email ?? ""),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Email, user.Email ?? ""),
new Claim("id", user.Id)
};
var userRoles = _userManager.GetRolesAsync(user);
userRoles.Wait();
foreach (var role in userRoles.Result)
{
claims.Add(new Claim(ClaimTypes.Role, role));
}
var tokenDescriptor = new SecurityTokenDescriptor var tokenDescriptor = new SecurityTokenDescriptor
{ {
Subject = new ClaimsIdentity(claims), Subject = new ClaimsIdentity(new[]
{
new Claim(JwtRegisteredClaimNames.Sub, user.Email ?? ""),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Email, user.Email ?? ""),
new Claim("id", user.Id)
}),
Expires = DateTime.UtcNow.AddHours(3), Expires = DateTime.UtcNow.AddHours(3),
SigningCredentials = SigningCredentials =
new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
@ -263,7 +239,6 @@ public class IdentityService : IIdentityService
var refreshToken = new RefreshTokenEntity var refreshToken = new RefreshTokenEntity
{ {
Token = token.Id,
JwtId = token.Id, JwtId = token.Id,
UserId = user.Id, UserId = user.Id,
CreatedDate = DateTime.UtcNow, CreatedDate = DateTime.UtcNow,

View File

@ -181,7 +181,7 @@ public class CodeProjectWatcherJob
Tags = source.Tags, Tags = source.Tags,
Title = item.Title.Text, Title = item.Title.Text,
Url = itemUrl, Url = itemUrl,
PubDate = item.LastUpdatedTime.DateTime.ToUniversalTime(), PubDate = item.LastUpdatedTime.DateTime,
Thumbnail = parser.Data.Header.Image, Thumbnail = parser.Data.Header.Image,
Description = item.Title.Text, Description = item.Title.Text,
CodeIsRelease = isRelease, CodeIsRelease = isRelease,

View File

@ -105,7 +105,7 @@ public class RssWatcherJob
Title = post.Title.Text, Title = post.Title.Text,
Tags = FetchTags(post), Tags = FetchTags(post),
Url = articleUrl, Url = articleUrl,
PubDate = post.PublishDate.DateTime.ToUniversalTime(), PubDate = post.PublishDate.DateTime,
Thumbnail = meta.Data.Header.Image, Thumbnail = meta.Data.Header.Image,
Description = meta.Data.Header.Description, Description = meta.Data.Header.Description,
SourceId = sourceId SourceId = sourceId

View File

@ -56,9 +56,7 @@ public class YoutubeWatcherJob
private void Execute() private void Execute()
{ {
var totalSources = _source.TotalByTypeAsync(SourceTypes.YouTube); var sources = _source.ListByType(SourceTypes.YouTube, 100);
var sources = _source.ListByType(SourceTypes.YouTube, 0);
foreach (var source in sources) foreach (var source in sources)
{ {
@ -167,7 +165,7 @@ public class YoutubeWatcherJob
Title = post.Title.Text, Title = post.Title.Text,
Tags = FetchTags(post), Tags = FetchTags(post),
Url = articleUrl, Url = articleUrl,
PubDate = post.PublishDate.DateTime.ToUniversalTime(), PubDate = post.PublishDate.DateTime,
Thumbnail = videoDetails.Data.Header.Image, Thumbnail = videoDetails.Data.Header.Image,
Description = videoDetails.Data.Header.Description, Description = videoDetails.Data.Header.Description,
SourceId = sourceId, SourceId = sourceId,