diff --git a/Client/Index.razor b/Client/Index.razor
index 2d30136..6282f6e 100644
--- a/Client/Index.razor
+++ b/Client/Index.razor
@@ -256,10 +256,18 @@ else
{
_blogEditor = UserSecurity.IsAuthorized(PageState.User, PermissionNames.Edit, ModuleState.PermissionList) && PageState.EditMode;
- if (PageState.QueryString.ContainsKey("guid"))
+ if (PageState.QueryString.ContainsKey("guid") && PageState.QueryString.ContainsKey("action"))
{
- await BlogSubscriberService.DeleteBlogSubscriberAsync(ModuleState.ModuleId, PageState.QueryString["guid"]);
- AddModuleMessage(Localizer["Unsubscribed"], MessageType.Success);
+ if (PageState.QueryString["action"] == "unsubscribe")
+ {
+ await BlogSubscriberService.DeleteBlogSubscriberAsync(ModuleState.ModuleId, PageState.QueryString["guid"]);
+ AddModuleMessage(Localizer["Unsubscribed"], MessageType.Success);
+ }
+ if (PageState.QueryString["action"] == "verify")
+ {
+ await BlogSubscriberService.UpdateBlogSubscriberAsync(ModuleState.ModuleId, PageState.QueryString["guid"]);
+ AddModuleMessage(Localizer["Verified"], MessageType.Success);
+ }
}
if (PageState.QueryString.ContainsKey("comment") && PageState.QueryString.ContainsKey("created"))
diff --git a/Client/ModuleInfo.cs b/Client/ModuleInfo.cs
index 95bef44..bb9e14d 100644
--- a/Client/ModuleInfo.cs
+++ b/Client/ModuleInfo.cs
@@ -9,8 +9,8 @@ public class ModuleInfo : IModule
{
Name = "Blog",
Description = "Blog",
- Version = "5.2.0",
- ReleaseVersions = "1.0.0,1.0.1,1.0.3,1.0.4,1.0.5,1.0.6,5.0.0,5.0.1,5.0.2,5.0.3,5.1.0,5.2.0",
+ Version = "5.2.1",
+ ReleaseVersions = "1.0.0,1.0.1,1.0.3,1.0.4,1.0.5,1.0.6,5.0.0,5.0.1,5.0.2,5.0.3,5.1.0,5.2.0,5.2.1",
ServerManagerType = "Oqtane.Blogs.Manager.BlogManager, Oqtane.Blogs.Server.Oqtane",
Dependencies = "Oqtane.Blogs.Shared.Oqtane",
SettingsType = "Oqtane.Blogs.Settings, Oqtane.Blogs.Client.Oqtane",
diff --git a/Client/Resources/Oqtane.Blogs.Index.resx b/Client/Resources/Oqtane.Blogs.Index.resx
index f5ca7a4..af69896 100644
--- a/Client/Resources/Oqtane.Blogs.Index.resx
+++ b/Client/Resources/Oqtane.Blogs.Index.resx
@@ -139,7 +139,7 @@
Error Loading Blogs
- Your Email Subscription Has Been Activated
+ Your Email Subscription Has Been Received. Please Check Your Email For Further Instructions.
Your Email
@@ -174,4 +174,7 @@
Manage Categories
+
+ You Have Successfully Verified Your Email Address
+
\ No newline at end of file
diff --git a/Client/Services/BlogSubscriberService.cs b/Client/Services/BlogSubscriberService.cs
index 363ac2b..0a16662 100644
--- a/Client/Services/BlogSubscriberService.cs
+++ b/Client/Services/BlogSubscriberService.cs
@@ -10,7 +10,7 @@ namespace Oqtane.Blogs.Services
public interface IBlogSubscriberService
{
Task AddBlogSubscriberAsync(BlogSubscriber BlogSubscriber);
-
+ Task UpdateBlogSubscriberAsync(int ModuleId, string Guid);
Task DeleteBlogSubscriberAsync(int ModuleId, string Guid);
}
@@ -30,6 +30,11 @@ public async Task AddBlogSubscriberAsync(BlogSubscriber BlogSubscriber)
await PostJsonAsync(Apiurl, BlogSubscriber);
}
+ public async Task UpdateBlogSubscriberAsync(int ModuleId, string Guid)
+ {
+ await PutAsync($"{Apiurl}/{ModuleId}/{Guid}");
+ }
+
public async Task DeleteBlogSubscriberAsync(int ModuleId, string Guid)
{
await DeleteAsync($"{Apiurl}/{ModuleId}/{Guid}");
diff --git a/Client/Widgets/ModuleInfo.cs b/Client/Widgets/ModuleInfo.cs
index 8824f5a..2fd4035 100644
--- a/Client/Widgets/ModuleInfo.cs
+++ b/Client/Widgets/ModuleInfo.cs
@@ -9,8 +9,7 @@ public class ModuleInfo : IModule
{
Name = "Blog Widgets",
Description = "Blog Widgets",
- Version = "5.2.0",
- ReleaseVersions = "5.2.0",
+ Version = "5.2.1",
Dependencies = "Oqtane.Blogs.Shared.Oqtane",
SettingsType = "Oqtane.Blogs.Widgets.Settings, Oqtane.Blogs.Client.Oqtane",
PackageName = "Oqtane.Blogs.Widgets"
diff --git a/Server/Controllers/BlogController.cs b/Server/Controllers/BlogController.cs
index 547ad67..e12b4ae 100644
--- a/Server/Controllers/BlogController.cs
+++ b/Server/Controllers/BlogController.cs
@@ -151,13 +151,16 @@ public int Notify(int id)
// this will likely need to be asynchronous in the future as it may timeout
foreach (var subscriber in _blogSubscriberRepository.GetBlogSubscribers(blog.ModuleId))
{
- var body = blog.PublishedBlogContent.Summary;
- body += $"
Read Full Article: {url}";
- var unsubscribe = rooturl + Utilities.NavigateUrl(alias.Path, pagepath, "guid=" + subscriber.Guid);
- body += $"
Unsubscribe: {unsubscribe}";
- var notification = new Notification(alias.SiteId, "", sender, "", subscriber.Email, blog.Title, body);
- _notificationRepository.AddNotification(notification);
- subscribers++;
+ if (subscriber.IsVerified)
+ {
+ var body = blog.PublishedBlogContent.Summary;
+ body += $"
Read Full Article: {url}";
+ var unsubscribe = rooturl + Utilities.NavigateUrl(alias.Path, pagepath, "guid=" + subscriber.Guid + "&action=unsubscribe");
+ body += $"
Unsubscribe: {unsubscribe}";
+ var notification = new Notification(alias.SiteId, "", sender, "", subscriber.Email, blog.Title, body);
+ _notificationRepository.AddNotification(notification);
+ subscribers++;
+ }
}
}
}
diff --git a/Server/Controllers/BlogSubscriberController.cs b/Server/Controllers/BlogSubscriberController.cs
index 47612e5..9db1ab2 100644
--- a/Server/Controllers/BlogSubscriberController.cs
+++ b/Server/Controllers/BlogSubscriberController.cs
@@ -8,6 +8,9 @@
using Oqtane.Controllers;
using System.Linq;
using System;
+using Oqtane.Models;
+using Oqtane.Repository;
+using Oqtane.Extensions;
namespace Oqtane.Blogs.Controllers
{
@@ -15,28 +18,58 @@ namespace Oqtane.Blogs.Controllers
public class BlogSubscriberController : ModuleControllerBase
{
private readonly IBlogSubscriberRepository _BlogSubscriberRepository;
+ private readonly ISettingRepository _SettingRepository;
+ private readonly INotificationRepository _NotificationRepository;
- public BlogSubscriberController(IBlogSubscriberRepository BlogSubscriberRepository, ILogManager logger, IHttpContextAccessor accessor) : base(logger,accessor)
+ public BlogSubscriberController(IBlogSubscriberRepository BlogSubscriberRepository, ISettingRepository SettingRepository, INotificationRepository NotificationRepository, ILogManager logger, IHttpContextAccessor accessor) : base(logger,accessor)
{
_BlogSubscriberRepository = BlogSubscriberRepository;
+ _SettingRepository = SettingRepository;
+ _NotificationRepository = NotificationRepository;
}
- // POST api//5
+ // POST api/
[HttpPost]
[IgnoreAntiforgeryToken]
public void Post([FromBody] BlogSubscriber BlogSubscriber)
{
if (ModelState.IsValid && Utilities.IsValidEmail(BlogSubscriber.Email))
{
+ BlogSubscriber.IsVerified = false;
BlogSubscriber.Guid = Guid.NewGuid().ToString();
BlogSubscriber = _BlogSubscriberRepository.AddBlogSubscriber(BlogSubscriber);
+
if (BlogSubscriber != null)
{
_logger.Log(LogLevel.Information, this, LogFunction.Create, "Blog Subscriber Added {BlogSubscriber}", BlogSubscriber);
+
+ var settings = _SettingRepository.GetSettings(EntityNames.Module, BlogSubscriber.ModuleId);
+ var alias = HttpContext.GetAlias();
+ var pagepath = settings.First(item => item.SettingName == "PagePath").SettingValue;
+ var sender = settings.First(item => item.SettingName == "Sender").SettingValue;
+ var body = "Thank You For Subscribing To Our Blog. Please Verify Your Email Address By Clicking The Link Below.";
+ var url = alias.Protocol + alias.Name + Utilities.NavigateUrl(alias.Path, pagepath, "guid=" + BlogSubscriber.Guid + "&action=verify");
+ body += $"
Verify: {url}";
+ var notification = new Notification(alias.SiteId, "", sender, "", BlogSubscriber.Email, "Blog Subscription", body);
+ _NotificationRepository.AddNotification(notification);
}
}
}
+ // PUT api//5
+ [HttpPut("{moduleid}/{guid}")]
+ [IgnoreAntiforgeryToken]
+ public void Put(int moduleid, string guid)
+ {
+ BlogSubscriber BlogSubscriber = _BlogSubscriberRepository.GetBlogSubscribers(moduleid).FirstOrDefault(item => item.Guid == guid);
+ if (BlogSubscriber != null)
+ {
+ BlogSubscriber.IsVerified = true;
+ BlogSubscriber = _BlogSubscriberRepository.UpdateBlogSubscriber(BlogSubscriber);
+ _logger.Log(LogLevel.Information, this, LogFunction.Update, "Blog Subscriber Updated {BlogSubscriber}", BlogSubscriber);
+ }
+ }
+
// DELETE api//5/guid
[HttpDelete("{moduleid}/{guid}")]
[IgnoreAntiforgeryToken]
diff --git a/Server/Migrations/05020101_AddBlogSubscriberIsVerified.cs b/Server/Migrations/05020101_AddBlogSubscriberIsVerified.cs
new file mode 100644
index 0000000..9a35a19
--- /dev/null
+++ b/Server/Migrations/05020101_AddBlogSubscriberIsVerified.cs
@@ -0,0 +1,31 @@
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Oqtane.Databases.Interfaces;
+using Oqtane.Migrations;
+using Oqtane.Blogs.Migrations.EntityBuilders;
+using Oqtane.Blogs.Repository;
+
+namespace Oqtane.Blogs.Migrations
+{
+ [DbContext(typeof(BlogContext))]
+ [Migration("Blog.05.02.01.01")]
+ public class AddBlogSubscriberIsVerified : MultiDatabaseMigration
+ {
+ public AddBlogSubscriberIsVerified(IDatabase database) : base(database)
+ {
+ }
+
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ var blogSubscriberEntityBuilder = new BlogSubscriberEntityBuilder(migrationBuilder, ActiveDatabase);
+ blogSubscriberEntityBuilder.AddBooleanColumn("IsVerified", true);
+ blogSubscriberEntityBuilder.UpdateColumn("IsVerified", "1", "bool", "");
+ }
+
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ var blogSubscriberEntityBuilder = new BlogSubscriberEntityBuilder(migrationBuilder, ActiveDatabase);
+ blogSubscriberEntityBuilder.DropColumn("IsVerified");
+ }
+ }
+}
diff --git a/Server/Repository/BlogSubscriberRepository.cs b/Server/Repository/BlogSubscriberRepository.cs
index fd0c71f..227102c 100644
--- a/Server/Repository/BlogSubscriberRepository.cs
+++ b/Server/Repository/BlogSubscriberRepository.cs
@@ -10,6 +10,7 @@ public interface IBlogSubscriberRepository
{
IEnumerable GetBlogSubscribers(int ModuleId);
BlogSubscriber AddBlogSubscriber(BlogSubscriber BlogSubscriber);
+ BlogSubscriber UpdateBlogSubscriber(BlogSubscriber BlogSubscriber);
void DeleteBlogSubscriber(int SubscriberId);
}
@@ -40,6 +41,14 @@ public BlogSubscriber AddBlogSubscriber(BlogSubscriber BlogSubscriber)
return null;
}
+ public BlogSubscriber UpdateBlogSubscriber(BlogSubscriber BlogSubscriber)
+ {
+ using var db = _dbContextFactory.CreateDbContext();
+ db.Entry(BlogSubscriber).State = EntityState.Modified;
+ db.SaveChanges();
+ return BlogSubscriber;
+ }
+
public void DeleteBlogSubscriber(int BlogSubscriberId)
{
using var db = _dbContextFactory.CreateDbContext();
diff --git a/Shared/Models/Blog.cs b/Shared/Models/Blog.cs
index 18780ef..eff706b 100644
--- a/Shared/Models/Blog.cs
+++ b/Shared/Models/Blog.cs
@@ -2,8 +2,6 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
-using System.Security.Cryptography;
-using Oqtane.Blogs.Shared;
using Oqtane.Models;
namespace Oqtane.Blogs.Models
diff --git a/Shared/Models/BlogSubscriber.cs b/Shared/Models/BlogSubscriber.cs
index f18b2a3..c95a531 100644
--- a/Shared/Models/BlogSubscriber.cs
+++ b/Shared/Models/BlogSubscriber.cs
@@ -9,6 +9,7 @@ public class BlogSubscriber : IAuditable
public int ModuleId { get; set; }
public string Email { get; set; }
public string Guid { get; set; }
+ public bool IsVerified { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedOn { get; set; }