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);
            }
        }
Пример #4
0
        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));
        }
Пример #5
0
        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());
        }
Пример #6
0
        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());
        }
Пример #7
0
        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());
        }
Пример #8
0
        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));
            }
        }
Пример #9
0
        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);
        }
Пример #10
0
        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));
            }
        }