Created
July 27, 2017 21:49
-
-
Save Kikimora/ef1715db5dbb41554cf6ea974894a8ff to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Runtime.Serialization; | |
using System.Threading.Tasks; | |
using Avend.API.Infrastructure; | |
using Avend.API.Infrastructure.Validation; | |
using Avend.API.Model; | |
using Avend.API.Services.Profile; | |
using Avend.API.Validation.Util; | |
using Microsoft.EntityFrameworkCore; | |
using Microsoft.Extensions.Configuration; | |
using Qoden.Validation; | |
namespace Avend.API.Services.Subscriptions | |
{ | |
[DataContract] | |
public class UserInviteRequestDto | |
{ | |
[DataMember(Name = "first_name")] | |
public string FirstName { get; set; } | |
[DataMember(Name = "last_name")] | |
public string LastName { get; set; } | |
[DataMember(Name = "email")] | |
public string Email { get; set; } | |
[DataMember(Name = "text")] | |
public string InviteText { get; set; } | |
public static UserInviteRequestDto From(SubscriptionInvite invite) | |
{ | |
return new UserInviteRequestDto | |
{ | |
FirstName = invite.FirstName, | |
LastName = invite.LastName, | |
Email = invite.Email, | |
InviteText = invite.InviteText | |
}; | |
} | |
} | |
public class InviteService | |
{ | |
private readonly DbContextOptions<AvendDbContext> _dbOptions; | |
private readonly ISendGrid _sendgrid; | |
private readonly UserContext _userContext; | |
private readonly EmailTemplateRecord _inviteTemplate; | |
private readonly IConfiguration _config; | |
public InviteService( | |
DbContextOptions<AvendDbContext> dbOptions, | |
UserContext userContext, | |
ISendGrid sendgrid, | |
IConfiguration config) | |
{ | |
Assert.Argument(dbOptions, nameof(dbOptions)).NotNull(); | |
Assert.Argument(userContext, nameof(userContext)).NotNull(); | |
Assert.Argument(sendgrid, nameof(sendgrid)).NotNull(); | |
Assert.Argument(config, nameof(config)).NotNull(); | |
_dbOptions = dbOptions; | |
_sendgrid = sendgrid; | |
_userContext = userContext; | |
_config = config; | |
_inviteTemplate = new EmailTemplateRecord() | |
{ | |
Subject = _config.GetSection("InviteEmail:Subject").Value, | |
Message = new Dictionary<string, string>() | |
{ | |
{"text/plain", _config.GetSection("InviteEmail:text/plain").Value}, | |
{"text/html", _config.GetSection("InviteEmail:text/html").Value}, | |
} | |
}; | |
} | |
public async Task AcceptInvite(Guid userUid, string inviteCode) | |
{ | |
Assert.Argument(inviteCode, nameof(inviteCode)).NotNull(); | |
using (var db = new AvendDbContext(_dbOptions)) | |
{ | |
var member = new SubscriptionMember(null, db); | |
await member.Load(userUid); | |
member.AssertValidMember(); | |
var invite = member.AcceptInvite(inviteCode); | |
Check.Value(invite, "invite", AvendErrors.NotFound).NotNull("Invite not found"); | |
await db.SaveChangesAsync(); | |
//this feels like a hack but I don't see any other good way around (averbin) | |
_userContext.Subscription = SubscriptionDto.From(invite.Subscription); | |
_userContext.Tenant = TenantDto.From(invite.Subscription); | |
} | |
} | |
public async Task<SubscriptionMemberDto> InviteUser(UserInviteRequestDto inviteRequest, Guid? subscriptionUid) | |
{ | |
if (_userContext.Role == UserRole.SuperAdmin) | |
{ | |
Check.Value(subscriptionUid).HasValue("Super Admin must supply subscription uid"); | |
} | |
else if (_userContext.Role == UserRole.Admin) | |
{ | |
subscriptionUid = _userContext.Subscription.Uid.GetValueOrDefault(); | |
} | |
else | |
{ | |
var error = new Error("Not found"); | |
error.NotFound(); | |
throw new ErrorException(error); | |
} | |
var validator = new Validator(); | |
validator.CheckDataMember(inviteRequest, x => x.Email).IsEmail(); | |
validator.CheckDataMember(inviteRequest, x => x.FirstName).IsShortText(); | |
validator.CheckDataMember(inviteRequest, x => x.LastName).IsShortText(); | |
inviteRequest.InviteText = inviteRequest.InviteText ?? string.Empty; | |
validator.Throw(); | |
using (var db = new AvendDbContext(_dbOptions)) | |
{ | |
var admin = new SubscriptionAdmin(_userContext, db); | |
admin.ManageSubscription(subscriptionUid.GetValueOrDefault()); | |
var invite = admin.Invite(inviteRequest); | |
await SendInvite(invite, db); | |
return SubscriptionMemberDto.From(invite); | |
} | |
} | |
public async Task<UserInviteRequestDto> GetInvite(string inviteCode) | |
{ | |
using (var db = new AvendDbContext(_dbOptions)) | |
{ | |
var repo = new SubscriptionMemberRepository(db); | |
var invite = await repo.FindInviteByIdAsync(inviteCode); | |
Check.Value(invite, onError: AvendErrors.NotFound).NotNull("Not found"); | |
Check.Value(invite.Accepted, onError: AvendErrors.NotFound).IsFalse("Invite already accepted"); | |
return UserInviteRequestDto.From(invite); | |
} | |
} | |
public async Task<SubscriptionMemberDto> ResendInvite(Guid uid) | |
{ | |
var rateLimit = _config.GetSection("RateLimit:ResendInvite").Get<float>(); | |
using (var db = new AvendDbContext(_dbOptions)) | |
{ | |
var admin = new SubscriptionAdmin(_userContext, db); | |
var invite = admin.ReInvite(uid); | |
Check.Value(invite, onError: AvendErrors.NotFound).NotNull("Invite not found"); | |
var sentLastTime = invite.UpdatedAt.GetValueOrDefault(invite.CreatedAt); | |
var nextInvite = sentLastTime + TimeSpan.FromSeconds(rateLimit); | |
Check.Value(nextInvite) | |
.Less(DateTime.Now.ToUniversalTime(), "Cannot resend invite. Please wait few minutes.", | |
AvendErrors.RateLimit); | |
await SendInvite(invite, db); | |
return SubscriptionMemberDto.From(invite); | |
} | |
} | |
private async Task SendInvite(SubscriptionInvite invite, AvendDbContext db) | |
{ | |
var message = new SendGridMessage() | |
{ | |
Email = invite.Email, | |
Personalization = new Qoden.Reflection.Record(invite) | |
}; | |
var sendResult = await _sendgrid.Send(_inviteTemplate.Subject, _inviteTemplate.Message, new[] {message}); | |
Check.Value(sendResult).IsTrue("Invite email send failed"); | |
await db.SaveChangesAsync(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment