private void NotifyOrgAdminAboutApprovedRequest(Organisation organisation, OrgUser orgUser) { if (organisation.RootUserId.HasValue) { var orgAdmin = UnitOfWork.OrgUsersRepository .AllAsNoTracking .Where(x => x.Id == organisation.RootUserId.Value) .SingleOrDefault(); var rootIndex = WebHelpers.GetRootIndexPath(); var url = $"{Request.RequestUri.Scheme}://{Request.RequestUri.Authority}/{rootIndex}#!/users/mobile/"; var emailBody = @"<p>A new user has joined your organisation: <strong>" + orgUser.UserName + @"</strong>.</p> <p>The user's personal case is now filed under your organisation and you have access to it.</p> <p>You can remove this user whenever you like, and put them back under OnRecord.</p> <p><br></p> <p>View the <a href='" + url + @"'>directory of mobile users</a> on the dashboard.</p>"; var orgAdminEmail = new Email { To = orgAdmin.Email, Subject = $"User joined organization - {orgUser.UserName}", Content = WebHelpers.GenerateEmailTemplate(emailBody, "A user has joined your organization") }; UnitOfWork.EmailsRepository.InsertOrUpdate(orgAdminEmail); } }
private void NotifyOrgAdminAboutNewRequest(Organisation organisation) { if (organisation.RootUser != null) { var orgAdmin = UnitOfWork.OrgUsersRepository .AllAsNoTracking .Where(x => x.Id == organisation.RootUser.Id) .SingleOrDefault(); var rootIndex = WebHelpers.GetRootIndexPath(); var url = $"{Request.RequestUri.Scheme}://{Request.RequestUri.Authority}/{rootIndex}#!/organisations/connection-requests/"; var content = @"<p>User name: <b>" + CurrentOrgUser.UserName + @"</b></p> <p><br></p> <p>View <a href='" + url + @"'>connection requests</a> on the dashboard.</p>"; var orgAdminEmail = new Email { To = orgAdmin.Email, Subject = $"A user has requested to join your organization", Content = WebHelpers.GenerateEmailTemplate(content, "A user has request to join your organization") }; UnitOfWork.EmailsRepository.InsertOrUpdate(orgAdminEmail); } }
private void NotifyEmailRecipientsAboutNewRequest(string organisationName) { var recipients = UnitOfWork.EmailRecipientsRepository .AllAsNoTracking .Where(x => x.OrgConnectionRequests == true) .ToList(); var rootIndex = WebHelpers.GetRootIndexPath(); var url = $"{Request.RequestUri.Scheme}://{Request.RequestUri.Authority}/{rootIndex}#!/organisations/connection-requests/"; var emailContent = @"<p>User name: <b>" + CurrentOrgUser.UserName + @"</b></p> <p>Organisation: <b>" + organisationName + @"</b></p> <p><br></p> <p>View <a href='" + url + @"'>connection requests</a> on the dashboard.</p>"; foreach (var recipient in recipients) { var recipientEmail = new Email { To = recipient.OrgUser.Email, Subject = $"A user has request to join an organization", Content = WebHelpers.GenerateEmailTemplate(emailContent, "A user has requested to join an organization") }; UnitOfWork.EmailsRepository.InsertOrUpdate(recipientEmail); } }
public HttpResponseMessage DownloadPdf(Guid id, bool timeline, bool locations, bool piechart) { if (id == Guid.Empty) { return(new HttpResponseMessage(HttpStatusCode.BadRequest)); } var session = ProjectSummaryPrintSessionService.GetSession(id); if (session == null) { return(new HttpResponseMessage(HttpStatusCode.NotFound)); } if (CurrentUser is OrgUser) { var subscriptionService = new SubscriptionService(UnitOfWork); if (!subscriptionService.HasAccessToExportPdf(CurrentOrgUser, session.ProjectId)) { return(new HttpResponseMessage(HttpStatusCode.Unauthorized)); } } var rootIndex = WebHelpers.GetRootIndexPath(); var authData = $"{{\"token\":\"{HttpContext.Current.Request.Headers["Authorization"].Substring(7)}\",\"email\":\"{CurrentUser.Email}\"}}"; var url = $"{Request.RequestUri.Scheme}://{Request.RequestUri.Authority}/{rootIndex}?authData={authData}#!/projects/summary/print/{id.ToString()}?timeline={timeline}&locations={locations}&piechart={piechart}"; var projectName = UnitOfWork.ProjectsRepository.Find(session.ProjectId).Name; var pdfFileName = $"{projectName}.pdf"; var pdfData = ConvertHtmlToPdf(url); return(CreatePdfResponseMessage(pdfData, projectName)); }
public async Task <IHttpActionResult> SendEmailConfirmation(SendEmailConfirmationModel model) { var user = await UserManager.FindByEmailAsync(model.Email); if (user == null) { return(NotFound()); } if (user.EmailConfirmed) { return(Ok()); } var code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id); var encodedCode = HttpUtility.UrlEncode(code); var rootIndex = WebHelpers.GetRootIndexPath(); var baseUrl = $"{Request.RequestUri.Scheme}://{Request.RequestUri.Authority}/{rootIndex}"; var callbackUrl = $"{baseUrl}#!/verify-email?userId={user.Id}&code={encodedCode}"; var content = @"<p>Your new account has been created. To complete your registration please confirm your email address by clicking the link below.</p> <p><a href='" + callbackUrl + @"'>Verify Email Address</a></p>"; var messageBody = WebHelpers.GenerateEmailTemplate(content, "Confirm your registration"); await UserManager.SendEmailAsync(user.Id, "Confirm your account", messageBody); return(Ok()); }
public async Task <IHttpActionResult> ForgotPassword(ForgotPasswordViewModel model) { if (model == null || !ModelState.IsValid) { return(BadRequest(ModelState)); } var user = await UserManager.FindByNameAsync(model.Email); // if user isn't found or the email isn't confirmed, don't reveal anything just return Ok. if (user == null || !(await UserManager.IsEmailConfirmedAsync(user.Id))) { return(Ok()); } // generate the reset token and send the email. string token = await UserManager.GeneratePasswordResetTokenAsync(user.Id); var encodedToken = HttpUtility.UrlEncode(token); var rootIndex = WebHelpers.GetRootIndexPath(); var baseUrl = $"{Request.RequestUri.Scheme}://{Request.RequestUri.Authority}/{rootIndex}"; var redirectLink = $"{baseUrl}#!/set-password?email={model.Email}&token={encodedToken}"; //var baseUrl = Request.RequestUri.GetLeftPart(UriPartial.Authority); //var redirectLink = baseUrl + "/wwwroot/dist/index.html#!/set-password?email=" + model.Email + "&token=" + encodedToken; //var content = @"<p>Click on <a href='" + redirectLink + @"'>this link</a> to set a new password.</p><br> // <p>If the link didn't work, copy/paste the token below and reset your password manually.</p> // <p style='color: gray; font-weight: italic'>" + encodedToken + @"</p>"; var content = @"<p>Click on <a href='" + redirectLink + @"'>this link</a> to set a new password.</p>"; var emailBody = WebHelpers.GenerateEmailTemplate(content, "Reset your password"); await UserManager.SendEmailAsync(user.Id, "Password reset request", emailBody); return(Ok()); }
public async Task <IHttpActionResult> Post([FromBody] OrgUserDTO value) { // not necessary to validate password, // because we generate a random password and // send it as part of the account confirmation email. //if (string.IsNullOrEmpty(value.Password)) // ModelState.AddModelError("Password", "Please provide password."); //if (value.Password != value.ConfirmPassword) // ModelState.AddModelError("ConfirmPassword", "'Password' and 'Confirm password' must be the same."); if (value.AccountType == AccountType.MobileAccount) { // the OrgUserType property is hidden in mobile-users' edit form. // so the Type is null at this point. fetch and populate. // TeamUser Type ID: 379c989a-9919-4338-a468-a7c20eb76e28 var teamUserType = UnitOfWork.OrgUserTypesRepository .AllAsNoTracking .Where(x => x.SystemName == "TeamUser") .SingleOrDefault(); value.Type = Mapper.Map <OrgUserTypeDTO>(teamUserType); } var orguser = Mapper.Map <OrgUser>(value); orguser.UserName = orguser.Email; if (CurrentUser is SuperUser || CurrentUser is PlatformUser) { orguser.OrganisationId = Guid.Parse(value.Organisation.Id); orguser.Organisation = null; } else if (CurrentUser is OrgUser) { orguser.OrganisationId = CurrentOrgUser.OrganisationId.Value; } // generate a random password var randomPassword = System.Web.Security.Membership.GeneratePassword(12, 1); var identityResult = ServiceContext.UserManager.CreateSync(orguser, randomPassword); if (!identityResult.Succeeded) { throw new Exception(identityResult.Errors.ToString(". ")); } // assign roles by type. orguser.Type = UnitOfWork.OrgUserTypesRepository.Find(orguser.TypeId); UnitOfWork.UserManager.AssignRolesByUserType(orguser); var organisation = UnitOfWork.OrganisationRepository.Find(orguser.OrganisationId.Value); if (value.Type.Name.ToLower() == "administrator") { var projects = UnitOfWork.ProjectsRepository .AllAsNoTracking .Where(p => p.OrganisationId == orguser.OrganisationId.Value) .Select(x => x.Id) .ToList(); foreach (var projectId in projects) { var orgUserAssignment = new Assignment { ProjectId = projectId, OrgUserId = orguser.Id, CanView = true, CanAdd = true, CanEdit = true, CanDelete = true, CanExportPdf = true, CanExportZip = true }; UnitOfWork.AssignmentsRepository.InsertOrUpdate(orgUserAssignment); } UnitOfWork.Save(); } // create a project for this user var project = new Project() { Name = $"{orguser.FirstName} {orguser.Surname}", StartDate = DateTimeService.UtcNow, OrganisationId = organisation.Id, CreatedById = orguser.Id }; UnitOfWork.ProjectsRepository.InsertOrUpdate(project); UnitOfWork.Save(); // assign this user to their project. var assignment = new Assignment() { ProjectId = project.Id, OrgUserId = orguser.Id, CanView = true, CanAdd = true, CanEdit = true, CanDelete = true, CanExportPdf = true, // temporary. turn off in production. CanExportZip = true // temporary. turn off in production. }; UnitOfWork.AssignmentsRepository.InsertOrUpdate(assignment); // assign organisation admin to this project if (organisation.RootUser != null) { UnitOfWork.AssignmentsRepository.InsertOrUpdate(new Assignment { ProjectId = project.Id, OrgUserId = organisation.RootUserId.Value, CanView = true, CanAdd = true, CanEdit = true, CanDelete = true, CanExportPdf = true, CanExportZip = true }); } UnitOfWork.Save(); // set user's current project var _orgUser = UnitOfWork.OrgUsersRepository.Find(orguser.Id); _orgUser.CurrentProjectId = project.Id; UnitOfWork.OrgUsersRepository.InsertOrUpdate(_orgUser); UnitOfWork.Save(); // subscribe this user to the current organization if (!_orgUser.Subscriptions.Any()) { var subscription = new Subscription { IsActive = true, Type = UserSubscriptionType.Organisation, StartDate = DateTimeService.UtcNow, EndDate = null, Note = $"Joined organisation - {organisation.Name}", OrgUserId = _orgUser.Id, OrganisationId = organisation.Id }; UnitOfWork.SubscriptionsRepository.InsertOrUpdate(subscription); _orgUser.IsSubscribed = true; UnitOfWork.Save(); } // send account confirmation email var code = await UserManager.GenerateEmailConfirmationTokenAsync(orguser.Id); var encodedCode = HttpUtility.UrlEncode(code); var rootIndex = WebHelpers.GetRootIndexPath(); var baseUrl = $"{Request.RequestUri.Scheme}://{Request.RequestUri.Authority}/{rootIndex}"; var callbackUrl = $"{baseUrl}#!/verify-email?userId={orguser.Id}&code={encodedCode}"; var content = @"<p>Complete your registration by verifying your email address. Click the link below to continue.</p> <p><a href='" + callbackUrl + @"'>Verify Email Address</a></p><br> <p>Your password is <strong>" + randomPassword + @"</strong></p> <p>Make sure to change your password after you've signed in.</p> <p>For more information please read our <a href='https://onrecord.tech/privacy-policy/' target='_blank'>privacy policy</a> guide.</p>"; var emailBody = WebHelpers.GenerateEmailTemplate(content, "Welcome to OnRecord"); await UserManager.SendEmailAsync(orguser.Id, "Confirm your account", emailBody); MemoryCacher.DeleteStartingWith(CACHE_KEY); return(Ok()); }
public IHttpActionResult Post([FromBody] OrgRequestDTO model) { if (CurrentOrgUser.AccountType != AccountType.MobileAccount) { return(BadRequest("organisation requests can only be made by mobile users")); } if (string.IsNullOrEmpty(model.Name)) { return(BadRequest("organisation name is required")); } var existingOrg = UnitOfWork.OrganisationRepository .AllAsNoTracking .Where(x => x.Name == model.Name) .FirstOrDefault(); if (existingOrg != null) { return(BadRequest("an organisation with this name already exists")); } var requestCount = UnitOfWork.OrgRequestsRepository .AllAsNoTracking .Count(x => x.OrgUserId == CurrentOrgUser.Id && x.Name == model.Name); if (requestCount > 0) { return(BadRequest("you have already requested this organisation")); } try { var orgRequest = new OrgRequest { Name = model.Name, Address = model.Address, ContactName = model.ContactName, Email = model.Email, TelNumber = model.TelNumber, Postcode = model.Postcode, OrgUserId = CurrentOrgUser.Id }; UnitOfWork.OrgRequestsRepository.InsertOrUpdate(orgRequest); var onRecord = UnitOfWork.OrganisationRepository .AllAsNoTracking .Where(x => x.Name == "OnRecord") .SingleOrDefault(); var rootIndex = WebHelpers.GetRootIndexPath(); var url = $"{Request.RequestUri.Scheme}://{Request.RequestUri.Authority}/{rootIndex}#!/organisations/requests/"; var content = @"<p>User name: <b>" + CurrentOrgUser.UserName + @"</b></p> <p>Organisation: <b>" + model.Name + @"</b></p> <p><br></p> <p>View <a href='" + url + @"'>organization requests</a> on the dashboard.</p>"; if (onRecord.RootUserId.HasValue) { var onRecordAdmin = UnitOfWork.OrgUsersRepository.AllAsNoTracking .Where(x => x.Id == onRecord.RootUserId.Value) .SingleOrDefault(); var email = new Email { To = onRecordAdmin.Email, Subject = $"A user has requested an organization", Content = WebHelpers.GenerateEmailTemplate(content, "A user has requested an organization") }; UnitOfWork.EmailsRepository.InsertOrUpdate(email); } // find email recipients var recipients = UnitOfWork.EmailRecipientsRepository .AllAsNoTracking .Where(x => x.OrgRequests == true) .ToList(); foreach (var recipient in recipients) { var recipientEmail = new Email { To = recipient.OrgUser.Email, Subject = $"A user has request an organization", Content = WebHelpers.GenerateEmailTemplate(content, "A user has request an organization") }; UnitOfWork.EmailsRepository.InsertOrUpdate(recipientEmail); } UnitOfWork.Save(); MemoryCacher.DeleteStartingWith(CACHE_KEY); return(Ok()); } catch (Exception ex) { return(InternalServerError(ex)); } }
private HttpResponseMessage ExportZipFile(ProjectSummaryPrintSessionDTO session, Guid id, bool timeline, bool locations, bool piechart) { if (CurrentOrgUser != null) { var project = UnitOfWork.ProjectsRepository.Find(session.ProjectId); var assignment = project.Assignments.SingleOrDefault(a => a.OrgUserId == CurrentOrgUser.Id); if (assignment == null || !assignment.CanExportZip) { return(new HttpResponseMessage(HttpStatusCode.Forbidden)); } } var rootIndex = WebHelpers.GetRootIndexPath(); var authData = $"{{\"token\":\"{HttpContext.Current.Request.Headers["Authorization"].Substring(7)}\",\"email\":\"{CurrentUser.Email}\"}}"; var url = $"{Request.RequestUri.Scheme}://{Request.RequestUri.Authority}/{rootIndex}?authData={authData}#!/projects/summary/print/{id.ToString()}?timeline={timeline}&locations={locations}&piechart={piechart}"; var surveys = UnitOfWork.FilledFormsRepository.AllAsNoTracking .Where(s => session.SurveyIds.Contains(s.Id)).ToList(); var rootFolder = HostingEnvironment.MapPath("/ExportTemp"); if (Directory.Exists(rootFolder)) { Directory.Delete(rootFolder, true); } Directory.CreateDirectory(rootFolder); foreach (var survey in surveys) { var attachments = UnitOfWork.AttachmentsRepository.AllAsNoTracking .Where(a => a.FormValue.FilledFormId == survey.Id).ToList(); foreach (var attch in attachments) { string folderPath = string.Empty; if (!string.IsNullOrEmpty(survey.Description)) { var sanitizedFileName = WebHelpers.SanitizeFileName(survey.FormTemplate.Title); folderPath = HostingEnvironment.MapPath($"/ExportTemp/{survey.Serial}_{sanitizedFileName}"); } else { folderPath = HostingEnvironment.MapPath($"/ExportTemp/{survey.Serial}"); } if (!Directory.Exists(folderPath)) { Directory.CreateDirectory(folderPath); } try { var filePath = HostingEnvironment.MapPath(attch.Url); var fileInfo = new FileInfo(filePath); var dest = Path.Combine(folderPath, attch.FileName); fileInfo.CopyTo(dest); } catch (Exception ex) { Debug.WriteLine(ex); } } } var projectName = UnitOfWork.ProjectsRepository.Find(session.ProjectId).Name; var pdfFileName = $"{projectName}.pdf"; var pdfData = ConvertHtmlToPdf(url); var pdfFilePath = Path.Combine(rootFolder, pdfFileName); var fs = new FileStream(pdfFilePath, FileMode.Create); fs.Write(pdfData, 0, pdfData.Length); fs.Flush(); fs.Close(); var zipRootPath = HostingEnvironment.MapPath("/ZipTemp"); if (Directory.Exists(zipRootPath)) { Directory.Delete(zipRootPath, true); } Directory.CreateDirectory(zipRootPath); var zipFilename = $"{projectName}.zip"; var zipFilePath = Path.Combine(zipRootPath, zipFilename); ZipFile.CreateFromDirectory(rootFolder, zipFilePath); var zipData = System.IO.File.ReadAllBytes(zipFilePath); var response = CreateZipResponseMessage(zipData, zipFilename); Directory.Delete(rootFolder, true); Directory.Delete(zipRootPath, true); return(response); }
public async Task <IHttpActionResult> Register(RegisterBindingModel model) { if (!ModelState.IsValid) { return(BadRequest(ModelState)); } var organisation = UnitOfWork.OrganisationRepository.FindByName(model.OrganisationName); if (organisation == null) { ModelState.AddModelError("Organisation", "Organisation was not found!"); return(BadRequest(ModelState)); } var user = new OrgUser() { FirstName = model.FirstName, Surname = model.Surname, UserName = model.Email, Email = model.Email, OrganisationId = organisation.Id, IsRootUser = false, IsActive = true, TypeId = OrgUserTypesRepository.TeamUser.Id, IsMobileUser = true, IsWebUser = true, // this should be 'false' in live production. IsSubscribed = false, AccountType = AccountType.MobileAccount }; if (!string.IsNullOrEmpty(model.Address)) { user.Address = model.Address; } if (!string.IsNullOrEmpty(model.Gender)) { user.Gender = (User.GenderType)Enum.Parse(typeof(User.GenderType), model.Gender); } if (model.Birthdate.HasValue) { var localValue = TimeZone.CurrentTimeZone.ToLocalTime(model.Birthdate.Value); user.Birthdate = new DateTime(localValue.Year, localValue.Month, localValue.Day, 0, 0, 0, DateTimeKind.Utc); } IdentityResult result = await UserManager.CreateAsync(user, model.Password); if (!result.Succeeded) { return(GetErrorResult(result)); } user.Type = UnitOfWork.OrgUserTypesRepository.Find(user.TypeId); UnitOfWork.UserManager.AssignRolesByUserType(user); // create a project for this user var project = new Project() { Name = $"{model.FirstName} {model.Surname}", StartDate = DateTimeService.UtcNow, OrganisationId = organisation.Id, CreatedById = user.Id }; UnitOfWork.ProjectsRepository.InsertOrUpdate(project); UnitOfWork.Save(); // assign this user to their project. var assignment = new Assignment() { ProjectId = project.Id, OrgUserId = user.Id, CanView = true, CanAdd = true, CanEdit = false, CanDelete = false, CanExportPdf = true, // temporary. turn off in production. CanExportZip = true // temporary. turn off in production. }; UnitOfWork.AssignmentsRepository.InsertOrUpdate(assignment); // assign organisation admin to this project if (organisation.RootUser != null) { UnitOfWork.AssignmentsRepository.InsertOrUpdate(new Assignment { ProjectId = project.Id, OrgUserId = organisation.RootUserId.Value, CanView = true, CanAdd = true, CanEdit = true, CanDelete = true, CanExportPdf = true, CanExportZip = true }); } UnitOfWork.Save(); // set user's current project var _orgUser = UnitOfWork.OrgUsersRepository.Find(user.Id); _orgUser.CurrentProjectId = project.Id; UnitOfWork.OrgUsersRepository.InsertOrUpdate(_orgUser); UnitOfWork.Save(); // subscribe this user under OnRecord with full access. if (_orgUser.AccountType == AccountType.MobileAccount && !_orgUser.Subscriptions.Any()) { var onrecord = UnitOfWork.OrganisationRepository.AllAsNoTracking .Where(x => x.Name == "OnRecord") .SingleOrDefault(); var subscription = new Subscription { IsActive = true, Type = UserSubscriptionType.Organisation, StartDate = DateTimeService.UtcNow, EndDate = null, Note = $"Joined organisation - OnRecord", OrgUserId = user.Id, OrganisationId = onrecord.Id }; UnitOfWork.SubscriptionsRepository.InsertOrUpdate(subscription); _orgUser.IsSubscribed = true; UnitOfWork.Save(); } // send account confirmation email var code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id); var encodedCode = HttpUtility.UrlEncode(code); var rootIndex = WebHelpers.GetRootIndexPath(); var baseUrl = $"{Request.RequestUri.Scheme}://{Request.RequestUri.Authority}/{rootIndex}"; var callbackUrl = $"{baseUrl}#!/verify-email?userId={user.Id}&code={encodedCode}"; var content = @"<p>Your new account has been created. To complete your registration please confirm your email address by clicking the link below.</p> <p><a href='" + callbackUrl + @"'>Verify Email Address</a></p>"; var messageBody = WebHelpers.GenerateEmailTemplate(content, "Confirm your registration"); await UserManager.SendEmailAsync(user.Id, "Confirm your account", messageBody); // find email recipients var recipients = UnitOfWork.EmailRecipientsRepository.AllAsNoTracking .Where(x => x.NewMobileUsers == true) .ToList(); var url = $"{Request.RequestUri.Scheme}://{Request.RequestUri.Authority}/{WebHelpers.GetRootIndexPath()}#!/users/mobile/"; foreach (var recipient in recipients) { var emailContent = $"<p>First name: {model.FirstName}</p>" + $"<p>Surname: {model.Surname}</p>" + $"<p>Email: {model.Email}</p><br>" + $"<p>View <a href='{url}'>mobile users</a> on the dashboard.</p>"; var recipientEmail = new Email { To = recipient.OrgUser.Email, Subject = "A new mobile user has joined OnRecord", Content = WebHelpers.GenerateEmailTemplate(emailContent, "A new mobile user has joined OnRecord") }; UnitOfWork.EmailsRepository.InsertOrUpdate(recipientEmail); } try { UnitOfWork.Save(); return(Ok()); } catch (Exception ex) { return(InternalServerError(ex)); } }