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(); } }
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 }
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); }
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()); }
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)); }
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()); }
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); }
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); }
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); }
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()); }