Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add verification for blog subscribers #89

Merged
merged 1 commit into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions Client/Index.razor
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
Expand Down
4 changes: 2 additions & 2 deletions Client/ModuleInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
5 changes: 4 additions & 1 deletion Client/Resources/Oqtane.Blogs.Index.resx
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@
<value>Error Loading Blogs</value>
</data>
<data name="Activated" xml:space="preserve">
<value>Your Email Subscription Has Been Activated</value>
<value>Your Email Subscription Has Been Received. Please Check Your Email For Further Instructions.</value>
</data>
<data name="Email" xml:space="preserve">
<value>Your Email</value>
Expand Down Expand Up @@ -174,4 +174,7 @@
<data name="ManageCategories" xml:space="preserve">
<value>Manage Categories</value>
</data>
<data name="Verified" xml:space="preserve">
<value>You Have Successfully Verified Your Email Address</value>
</data>
</root>
7 changes: 6 additions & 1 deletion Client/Services/BlogSubscriberService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -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}");
Expand Down
3 changes: 1 addition & 2 deletions Client/Widgets/ModuleInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
17 changes: 10 additions & 7 deletions Server/Controllers/BlogController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 += $"<br /><br />Read Full Article: <a href=\"{url}\">{url}</a>";
var unsubscribe = rooturl + Utilities.NavigateUrl(alias.Path, pagepath, "guid=" + subscriber.Guid);
body += $"<br /><br />Unsubscribe: <a href=\"{unsubscribe}\">{unsubscribe}</a>";
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 += $"<br /><br />Read Full Article: <a href=\"{url}\">{url}</a>";
var unsubscribe = rooturl + Utilities.NavigateUrl(alias.Path, pagepath, "guid=" + subscriber.Guid + "&action=unsubscribe");
body += $"<br /><br />Unsubscribe: <a href=\"{unsubscribe}\">{unsubscribe}</a>";
var notification = new Notification(alias.SiteId, "", sender, "", subscriber.Email, blog.Title, body);
_notificationRepository.AddNotification(notification);
subscribers++;
}
}
}
}
Expand Down
37 changes: 35 additions & 2 deletions Server/Controllers/BlogSubscriberController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,35 +8,68 @@
using Oqtane.Controllers;
using System.Linq;
using System;
using Oqtane.Models;
using Oqtane.Repository;
using Oqtane.Extensions;

namespace Oqtane.Blogs.Controllers
{
[Route(ControllerRoutes.ApiRoute)]
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/<controller>/5
// POST api/<controller>
[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 += $"<br /><br />Verify: <a href=\"{url}\">{url}</a>";
var notification = new Notification(alias.SiteId, "", sender, "", BlogSubscriber.Email, "Blog Subscription", body);
_NotificationRepository.AddNotification(notification);
}
}
}

// PUT api/<controller>/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/<controller>/5/guid
[HttpDelete("{moduleid}/{guid}")]
[IgnoreAntiforgeryToken]
Expand Down
31 changes: 31 additions & 0 deletions Server/Migrations/05020101_AddBlogSubscriberIsVerified.cs
Original file line number Diff line number Diff line change
@@ -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");
}
}
}
9 changes: 9 additions & 0 deletions Server/Repository/BlogSubscriberRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public interface IBlogSubscriberRepository
{
IEnumerable<BlogSubscriber> GetBlogSubscribers(int ModuleId);
BlogSubscriber AddBlogSubscriber(BlogSubscriber BlogSubscriber);
BlogSubscriber UpdateBlogSubscriber(BlogSubscriber BlogSubscriber);
void DeleteBlogSubscriber(int SubscriberId);
}

Expand Down Expand Up @@ -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();
Expand Down
2 changes: 0 additions & 2 deletions Shared/Models/Blog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions Shared/Models/BlogSubscriber.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down