Esempio n. 1
0
        public User SignupUser([FromBody] UserSignup signup)
        {
            // signup request contains password, so mark it confidential, so the request body will NOT be logged
            //  to prevent passwords appearing in logs
            this.WebContext.Flags |= WebCallFlags.Confidential;

            //Validate
            OpContext.ThrowIfNull(signup, ClientFaultCodes.InvalidValue, "UserSignup", "UserSignup object may not be null.");
            OpContext.ValidateNotEmpty(signup.UserName, "UserName", "UserName may not be empty.");
            OpContext.ValidateNotEmpty(signup.Password, "Password", "Password may not be empty.");
            OpContext.ThrowValidation();
            var session = OpenSession();
            // check if user name is already taken
            var existingUser = session.EntitySet <IUser>().Where(u => u.UserName == signup.UserName).WithOptions(QueryOptions.ForceIgnoreCase).FirstOrDefault();

            OpContext.ThrowIf(existingUser != null, ClientFaultCodes.InvalidValue, "UserName", "User name {0} is already in use. Please choose other name.", signup.UserName);
            // create login and user
            var loginMgr = OpContext.App.GetService <ILoginManagementService>();
            var user     = session.NewUser(signup.UserName, UserType.Customer, signup.UserName);
            var login    = loginMgr.NewLogin(session, signup.UserName, signup.Password, loginId: user.Id, userId: user.Id); //Login.Id is the same as userID

            session.SaveChanges();
            // Let's create custom app event; we test here that this appEvent gets to AppEventLog
            //  log entries in web app are accumulated in buffered log attached to web call, and later
            // dumped to WebCallLog.OperationLog column as text. Except - errors and app events, they are
            // passed to global log as well.
            OpContext.WriteAppEvent("Customer", "Signup", $"Customer {signup.UserName} signed up.");
            return(user.ToModel());
        }
        private ILogin GetCurrentLogin(IEntitySession session)
        {
            var login = LoginManager.GetLogin(session);

            OpContext.ThrowIfNull(login, ClientFaultCodes.ObjectNotFound, "Login", "Login not found for user: {0}.", OpContext.User.UserName);
            return(login);
        }
        public bool SubmitPin(Guid factorId, string pin)
        {
            OpContext.ThrowIfEmpty(pin, ClientFaultCodes.ValueMissing, "pin", "Pin value missing");
            var session = OpenSession();
            var login   = GetCurrentLogin(session);
            var factor  = login.ExtraFactors.FirstOrDefault(f => f.Id == factorId);

            OpContext.ThrowIfNull(factor, ClientFaultCodes.ObjectNotFound, "factor", "Factor not found, ID: {0}", factorId);
            var processService = OpContext.App.GetService <ILoginProcessService>();
            var processes      = processService.GetActiveConfirmationProcesses(factor, LoginProcessType.FactorVerification);

            OpContext.ThrowIf(processes.Count == 0, ClientFaultCodes.ObjectNotFound, "LoginProcess", "Confirmation process not found or expired.");
            try {
                foreach (var process in processes)
                {
                    if (processService.SubmitPin(process, pin))
                    {
                        return(true);
                    }
                }
                return(false);
            } finally {
                session.SaveChanges();
            }
        }
Esempio n. 4
0
        public async Task SendPin([FromBody] SendPinRequest request)
        {
            OpContext.WebContext.MarkConfidential();
            OpContext.ThrowIfNull(request, ClientFaultCodes.ContentMissing, "SendPinRequest", "Pin request object must be provided.");
            OpContext.ValidateNotEmpty(request.ProcessToken, "ProcessToken", "Process token should be provided.");
            OpContext.ValidateNotEmpty(request.Factor, "Factor", "Factor (email or phone) should be provided.");
            OpContext.ThrowValidation();
            var session = OpContext.OpenSession();
            var process = GetActiveProcess(session, request.ProcessToken, confirmedOnly: false);

            if (process == null)
            {
                return; //no indication process exist or not
            }
            OpContext.ThrowIf(process.CurrentFactor != null, ClientFaultCodes.InvalidAction, "token", "The previous process step is not completed.");
            var iFactor = ProcessService.FindLoginExtraFactor(process.Login, request.Factor);

            //now having completed at least one extra factor, we can openly indicate that we could not find next factor
            OpContext.ThrowIfNull(iFactor, ClientFaultCodes.InvalidValue, "factor", "Login factor (email or phone) is not found for a user.");
            //Check that factor type is one in the pending steps
            var factorOk = process.PendingFactors.IsSet(iFactor.FactorType);

            OpContext.ThrowIf(!factorOk, ClientFaultCodes.InvalidValue, "factor", "Login factor type attempted (email or phone) is not pending in the process.");
            await ProcessService.SendPinAsync(process, iFactor, request.Factor); //we use factor from request, to avoid unencrypting twice
        }
Esempio n. 5
0
        public LoginResponse CompleteMultiFactorLogin([FromBody] MultifactorLoginRequest request)
        {
            var session = OpContext.OpenSession();
            var process = GetMutiFactorProcess(session, request.ProcessToken);

            OpContext.ThrowIfNull(process, ClientFaultCodes.ObjectNotFound, "processToken", "Login process not found or expired.");
            OpContext.ThrowIf(process.PendingFactors != ExtraFactorTypes.None, ClientFaultCodes.InvalidValue, "PendingFactors",
                              "Multi-factor login process not completed, verification pending: {0}.", process.PendingFactors);
            var login = process.Login;

            var loginService = OpContext.App.GetService <ILoginService>();
            var loginResult  = loginService.CompleteMultiFactorLogin(OpContext, login);
            var displayName  = OpContext.App.GetUserDispalyName(OpContext.User);

            session.SaveChanges();
            return(new LoginResponse()
            {
                Status = LoginAttemptStatus.Success, SessionId = loginResult.SessionId,
                UserName = login.UserName, UserDisplayName = displayName,
                UserId = login.UserId, AltUserId = login.AltUserId, LoginId = login.Id,
                PasswordExpiresDays = login.GetExpiresDays(), Actions = loginResult.Actions,
                LastLoggedInOn = loginResult.PreviousLoginOn,
                AuthenticationToken = CreateAuthToken()
            });
        }//method
        public BookOrder UpdateOrder(BookOrder order)
        {
            var session = OpenSession();
            var cart    = GetOpenOrder(session, LockType.ForUpdate, create: true);

            foreach (var item in order.Items)
            {
                OpContext.ThrowIf(item.Quantity < 0, ClientFaultCodes.InvalidValue, "Quantity", "Quantity may not be negative.");
                OpContext.ThrowIf(item.Quantity > 10, ClientFaultCodes.InvalidValue, "Quantity", "Quantity may not be more than 10.");
                var orderLine = cart.Lines.FirstOrDefault(ln => ln.Book.Id == item.Book.Id);
                if (orderLine == null)
                {
                    if (item.Quantity > 0)
                    {
                        var bk = session.GetEntity <IBook>(item.Book.Id);
                        OpContext.ThrowIfNull(bk, ClientFaultCodes.ObjectNotFound, "Book", "Book not found.");
                        cart.Add(bk, item.Quantity);
                        continue;
                    }
                }
                else //orderLine != null
                if (item.Quantity == 0)
                {
                    session.DeleteEntity(orderLine);
                }
                else
                {
                    orderLine.Quantity = item.Quantity;
                }
            }
            cart.ScheduleUpdateTotal();
            session.SaveChanges();
            EntityHelper.RefreshEntity(cart); //to make sure total from database is refreshed in entity
            return(cart.ToModel(details: true));
        }
        public void UpdateStatus(Guid loginId, [FromQuery] LoginStatusUpdate update)
        {
            var session = OpContext.OpenSession();
            var login   = _adminService.GetLogin(session, loginId);

            OpContext.ThrowIfNull(login, ClientFaultCodes.ObjectNotFound, "Login", "Login not found.");
            _adminService.UpdateStatus(login, update.Disable, update.Suspend);
        }
Esempio n. 8
0
        public PasswordStrength EvaluatePasswordStrength([FromBody] PasswordChangeInfo changeInfo)
        {
            OpContext.WebContext.MarkConfidential(); //prevent from logging password
            OpContext.ThrowIfNull(changeInfo, ClientFaultCodes.ContentMissing, "Password", "Password infomation missing.");
            var loginMgr = OpContext.App.GetService <ILoginManagementService>();
            var strength = loginMgr.EvaluatePasswordStrength(changeInfo.NewPassword);

            return(strength);
        }
        public void ChangePassword([FromBody] PasswordChangeInfo changeInfo)
        {
            OpContext.WebContext.MarkConfidential();
            OpContext.ThrowIfNull(changeInfo, ClientFaultCodes.ContentMissing, "Password", "Password change info is missing.");
            var session = OpenSession();
            var login   = GetCurrentLogin(session);

            LoginManager.ChangePassword(login, changeInfo.OldPassword, changeInfo.NewPassword);
            session.SaveChanges();
        }
        public BookOrder SubmitOrder(string coupon = null)
        {
            var session = OpenSession();
            var cart    = GetOpenOrder(session, LockType.ForUpdate);

            OpContext.ThrowIfNull(cart, ClientFaultCodes.InvalidAction, "Cart", "Cart is empty, cannot submit order.");
            cart.CompleteOrder(coupon);
            session.SaveChanges();
            return(cart.ToModel(details: true));
        }
        public void DeleteReview(Guid id)
        {
            var session = OpenSession();
            var review  = session.GetEntity <IBookReview>(id);

            OpContext.ThrowIfNull(review, ClientFaultCodes.ObjectNotFound,
                                  "ReviewId", "Review with ID '{0}' not found.", id);
            session.DeleteEntity(review);
            session.SaveChanges();
        }
        public void DeleteFactor(Guid id)
        {
            var session = OpenSession();
            var login   = GetCurrentLogin(session);
            var factor  = login.ExtraFactors.FirstOrDefault(f => f.Id == id);

            OpContext.ThrowIfNull(factor, ClientFaultCodes.ObjectNotFound, "factor", "Factor not found, ID: {0}", id);
            session.DeleteEntity(factor);
            session.SaveChanges();
            LoginManager.CheckLoginFactorsSetupCompleted(login);
        }
        public BookOrder CancelOrder()
        {
            //we use this args object to allow optional coupon parameter
            var session = OpenSession();
            var cart    = GetOpenOrder(session, LockType.ForUpdate);

            OpContext.ThrowIfNull(cart, ClientFaultCodes.InvalidAction, "Cart", "Cart is empty, cannot submit order.");
            cart.Status = OrderStatus.Canceled;
            session.SaveChanges();
            return(cart.ToModel(details: true));
        }
        public LoginInfo UpdateLoginInfo([FromBody] LoginInfo loginInfo)
        {
            var session = OpenSession();
            var login   = GetCurrentLogin(session);

            OpContext.ThrowIfNull(login, ClientFaultCodes.ContentMissing, "LoginInfo", "LoginInfo is missing.");
            OpContext.ThrowIf(loginInfo.Id != login.Id, ClientFaultCodes.InvalidValue, "Id", "Invalid login Id, must match current user's login id.");
            LoginManager.UpdateLogin(login, loginInfo);
            session.SaveChanges();
            return(login.ToModel());
        }
Esempio n. 15
0
        private ILoginProcess GetMutiFactorProcess(IEntitySession session, string token, bool throwIfNotFound = true)
        {
            OpContext.ThrowIfEmpty(token, ClientFaultCodes.ValueMissing, "token", "Process token may not be empty.");
            var processService = OpContext.App.GetService <ILoginProcessService>();
            var process        = processService.GetActiveProcess(session, LoginProcessType.MultiFactorLogin, token);

            if (throwIfNotFound)
            {
                OpContext.ThrowIfNull(process, ClientFaultCodes.ObjectNotFound, "LoginProcess", "Invalid login process token - process not found or expired.");
            }
            return(process);
        }
        public void DeleteOrderItem(Guid id)
        {
            var session = OpenSession();
            var itemEnt = session.GetEntity <IBookOrderLine>(id);

            OpContext.ThrowIfNull(itemEnt, ClientFaultCodes.ObjectNotFound, "BookId", "Book not found.");
            //Lock order
            var cart = GetOpenOrder(session, LockType.ForUpdate);

            session.DeleteEntity(itemEnt);
            itemEnt.Order.ScheduleUpdateTotal();
            session.SaveChanges();
        }
        public string GetGoogleAuthenticatorQrUrl(Guid id)
        {
            var session = OpenSession();
            var login   = GetCurrentLogin(session);
            var iFactor = session.GetEntity <ILoginExtraFactor>(id);

            OpContext.ThrowIfNull(iFactor, ClientFaultCodes.ObjectNotFound, "factor", "Factor not found, ID: {0}", id);
            //the following should be caught by Authorization
            OpContext.ThrowIf(iFactor.Login != login, ClientFaultCodes.InvalidAction, "id", "Factor does not belong to current user.");
            OpContext.ThrowIf(iFactor.FactorType != ExtraFactorTypes.GoogleAuthenticator, ClientFaultCodes.InvalidAction,
                              "FactorType", "Factor is not GoogleAuthenticator.");
            return(LoginManager.GetGoogleAuthenticatorQRUrl(iFactor));
        }
Esempio n. 18
0
        public bool SubmitQuestionAnswer(string token, [FromBody] SecretQuestionAnswer answer)
        {
            OpContext.WebContext.MarkConfidential();
            var session      = OpContext.OpenSession();
            var process      = GetMutiFactorProcess(session, token);
            var storedAnswer = process.Login.SecretQuestionAnswers.FirstOrDefault(a => a.Question.Id == answer.QuestionId);

            OpContext.ThrowIfNull(storedAnswer, ClientFaultCodes.InvalidValue, "questionId", "Question is not registered user question.");
            var processService = OpContext.App.GetService <ILoginProcessService>();
            var success        = processService.CheckSecretQuestionAnswer(process, storedAnswer.Question, answer.Answer);

            return(success);
        }
        public BookOrderItem AddOrderItem(BookOrderItem item)
        {
            var session = OpenSession();
            var bk      = session.GetEntity <IBook>(item.Book.Id);

            OpContext.ThrowIfNull(bk, ClientFaultCodes.ObjectNotFound, "BookId", "Book not found.");
            var cart    = GetOpenOrder(session, LockType.ForUpdate, create: true);
            var itemEnt = cart.Add(bk, item.Quantity);

            cart.ScheduleUpdateTotal();
            session.SaveChanges();
            return(itemEnt.ToModel());
        }
Esempio n. 20
0
        public bool VerifyPinForMultiFactor([FromBody] VerifyPinRequest request)
        {
            var session = OpContext.OpenSession();
            var process = GetMutiFactorProcess(session, request.ProcessToken);

            OpContext.ThrowIfNull(process, ClientFaultCodes.ObjectNotFound, "Process", "Process not found or expired.");
            OpContext.ThrowIfEmpty(request.Pin, ClientFaultCodes.ValueMissing, "Pin", "Pin value missing.");
            var processService = OpContext.App.GetService <ILoginProcessService>();
            var result         = processService.SubmitPin(process, request.Pin);

            session.SaveChanges();
            return(result);
        }
Esempio n. 21
0
        public bool VerifyEmailPin(string processToken, string pin)
        {
            OpContext.ThrowIfEmpty(processToken, ClientFaultCodes.ValueMissing, "processToken", "ProcessToken value missing");
            OpContext.ThrowIfEmpty(pin, ClientFaultCodes.ValueMissing, "pin", "Pin value missing");
            var session        = OpContext.OpenSession();
            var processService = OpContext.App.GetService <ILoginProcessService>();
            var process        = processService.GetActiveProcess(session, LoginProcessType.FactorVerification, processToken);

            OpContext.ThrowIfNull(process, ClientFaultCodes.ObjectNotFound, "processToken", "Login process not found or expired.");
            var result = processService.SubmitPin(process, pin);

            session.SaveChanges();
            return(result);
        }
Esempio n. 22
0
        public LoginResponse Login([FromBody] LoginRequest request)
        {
            OpContext.ThrowIfNull(request, ClientFaultCodes.ContentMissing, "LoginRequest", "Content object missing in API request.");
            OpContext.WebContext.Flags |= WebCallFlags.Confidential;
            //Login using LoginService

            var loginService = OpContext.App.GetService <ILoginService>();
            var loginResult  = loginService.Login(this.OpContext, request.UserName, request.Password, request.TenantId, request.DeviceToken);
            var login        = loginResult.Login;

            switch (loginResult.Status)
            {
            case LoginAttemptStatus.PendingMultifactor:
                var processService = OpContext.App.GetService <ILoginProcessService>();
                var token          = processService.GenerateProcessToken();
                var process        = processService.StartProcess(loginResult.Login, LoginProcessType.MultiFactorLogin, token);
                return(new LoginResponse()
                {
                    Status = LoginAttemptStatus.PendingMultifactor, MultiFactorProcessToken = token
                });

            case LoginAttemptStatus.AccountInactive:
                // return AccountInactive only if login allows to disclose membership
                var reportStatus = login.Flags.IsSet(LoginFlags.DoNotConcealMembership) ? LoginAttemptStatus.AccountInactive : LoginAttemptStatus.Failed;
                return(new LoginResponse()
                {
                    Status = reportStatus
                });

            case LoginAttemptStatus.Failed:
            default:
                return(new LoginResponse()
                {
                    Status = loginResult.Status
                });

            case LoginAttemptStatus.Success:
                var displayName = OpContext.App.GetUserDispalyName(loginResult.User);
                return(new LoginResponse()
                {
                    Status = LoginAttemptStatus.Success,
                    UserName = login.UserName, UserDisplayName = displayName,
                    UserId = login.UserId, AltUserId = login.AltUserId, LoginId = login.Id,
                    PasswordExpiresDays = login.GetExpiresDays(), Actions = loginResult.Actions, LastLoggedInOn = loginResult.PreviousLoginOn,
                    SessionId = loginResult.SessionId,
                    AuthenticationToken = CreateAuthToken()
                });
            }//switch
        }
        public OneTimePasswordInfo SetOneTimePassword(Guid loginId)
        {
            var session = OpContext.OpenSession();
            var login   = _adminService.GetLogin(session, loginId);

            OpContext.ThrowIfNull(login, ClientFaultCodes.ObjectNotFound, "Login", "Login not found.");
            var    loginSettings = OpContext.App.GetConfig <LoginModuleSettings>();
            string password      = _adminService.GenerateTempPassword();

            _adminService.SetOneTimePassword(login, password);
            return(new OneTimePasswordInfo()
            {
                Password = password, ExpiresHours = (int)loginSettings.OneTimePasswordExpiration.TotalHours
            });
        }
        public async Task <string> SendPin(Guid factorId)
        {
            var session = OpenSession();
            var login   = GetCurrentLogin(session);
            var factor  = login.ExtraFactors.FirstOrDefault(f => f.Id == factorId);

            OpContext.ThrowIfNull(factor, ClientFaultCodes.ObjectNotFound, "factor", "Factor not found, ID: {0}", factorId);
            var processService = OpContext.App.GetService <ILoginProcessService>();
            var token          = processService.GenerateProcessToken();
            var process        = processService.StartProcess(login, LoginProcessType.FactorVerification, token);
            var pin            = processService.GeneratePin(process, factor);
            await processService.SendPinAsync(process, factor);

            session.SaveChanges();
            return(process.Token);
        }
Esempio n. 25
0
        public async Task SendPinForMultiFactor([FromBody] SendPinRequest pinRequest)
        {
            var session = OpContext.OpenSession();
            var process = GetMutiFactorProcess(session, pinRequest.ProcessToken);

            OpContext.ThrowIf(process.CurrentFactor != null, ClientFaultCodes.InvalidAction, "token", "Factor verification pending, the previous process step is not completed.");
            var pendingFactorTypes = process.PendingFactors;

            OpContext.ThrowIf(!pendingFactorTypes.IsSet(pinRequest.FactorType), ClientFaultCodes.InvalidValue, "factortype", "Factor type is not pending in login process");
            var factor = process.Login.ExtraFactors.FirstOrDefault(f => f.FactorType == pinRequest.FactorType);

            OpContext.ThrowIfNull(factor, ClientFaultCodes.ObjectNotFound, "factor",
                                  "Login factor (email or phone) not setup in user account; factor type: {0}", pinRequest.FactorType);
            var processService = OpContext.App.GetService <ILoginProcessService>();
            await processService.SendPinAsync(process, factor);
        }
        public LoginExtraFactor UpdateFactor([FromBody] LoginExtraFactor factor)
        {
            var session = OpenSession();
            var login   = GetCurrentLogin(session);
            var iFactor = login.ExtraFactors.FirstOrDefault(f => f.Id == factor.Id);

            OpContext.ThrowIfNull(iFactor, ClientFaultCodes.ObjectNotFound, "factor", "Factor not found, ID: {0}", factor.Id);
            if (factor.Type == ExtraFactorTypes.GoogleAuthenticator)
            {
                factor.Value = Modules.Login.GoogleAuthenticator.GoogleAuthenticatorUtil.GenerateSecret();
            }
            var updFactor = LoginManager.UpdateFactor(iFactor, factor.Value);

            session.SaveChanges();
            LoginManager.CheckLoginFactorsSetupCompleted(login);
            return(updFactor);
        }
        private BookReview CreateUpdateReview(BookReview review, bool create)
        {
            OpContext.ThrowIfNull(review, ClientFaultCodes.ContentMissing, "Review", "Review object in message body is missing.");
            //find book
            var session = OpenSession();
            var bk      = session.GetEntity <IBook>(review.BookId);

            //Validate using ValidationExtensions methods
            //will throw and return BadRequest if book Id is invalid
            OpContext.ThrowIfNull(bk, ClientFaultCodes.ObjectNotFound, "BookId", "Book not found. ID={0}", review.BookId);
            //Validate input fields
            OpContext.ValidateNotEmpty(review.Caption, "Caption", "Caption may not be empty.");
            OpContext.ValidateNotEmpty(review.Review, "Review", "Review text may not be empty.");
            OpContext.ValidateMaxLength(review.Caption, 100, "Caption", "Caption text is too long.");
            // Review text is unlimited in database, but let's still limit it to 1000 chars
            OpContext.ValidateMaxLength(review.Review, 1000, "Review", "Review text is too long, must be under 1000 chars");
            OpContext.ValidateRange(review.Rating, 1, 5, "Rating", "Rating must be between 1 and 5");
            OpContext.ThrowValidation(); //will throw if any faults had been detected; will return BadRequest with list of faults in the body
            // get user;
            var user = session.GetEntity <IUser>(OpContext.User.UserId);

            // with AuthenticatedOnly attribute, we should always have user; still check just in case
            OpContext.ThrowIfNull(user, ClientFaultCodes.ObjectNotFound, "User", "Current user not identified.");

            //Create/update review entity
            IBookReview entReview;

            if (create)
            {
                entReview = session.NewReview(user, bk, review.Rating, review.Caption, review.Review);
            }
            else
            {
                entReview = session.GetEntity <IBookReview>(review.Id);
                OpContext.ThrowIfNull(entReview, ClientFaultCodes.ObjectNotFound, "Review", "Review object not found, ID={0}.", review.Id);
                entReview.Caption = review.Caption;
                entReview.Rating  = review.Rating;
                entReview.Review  = review.Review;
            }
            session.SaveChanges();
            return(entReview.ToModel(details: true));
        }
        public BookOrderItem UpdateOrderItem(BookOrderItem item)
        {
            var session = OpenSession();
            //Lock order
            var order   = session.GetEntity <IBookOrder>(item.OrderId, LockType.ForUpdate);
            var itemEnt = session.GetEntity <IBookOrderLine>(item.Id);

            OpContext.ThrowIfNull(itemEnt, ClientFaultCodes.ObjectNotFound, "BookId", "Book not found.");
            if (item.Quantity == 0)
            {
                session.DeleteEntity(itemEnt);
            }
            else
            {
                itemEnt.Quantity = item.Quantity;
            }
            itemEnt.Order.ScheduleUpdateTotal();
            session.SaveChanges();
            return(itemEnt.ToModel());
        }