/// <summary> /// Run the workflow associated with notification reply /// </summary> void RunReplyWorkflow(IWorkflowRunner runner, Workflow workflow, ReplyRecord reply) { if (workflow.WorkflowRunAsOwner != true) { throw new ArgumentException($"The provided workflow is not marked as run as owner. This should never occur. Workflow: ${workflow.Name}"); } var input = new Dictionary <string, object>(); var inputArg = workflow?.InputArgumentForAction?.As <ResourceArgument>(); if (inputArg != null) { if (inputArg.ConformsToType.Id == ReplyRecord.ReplyRecord_Type.Id) { input.Add(inputArg.Name, reply); } } // Set the context to the owner and start the workflow. var wfOwner = workflow.SecurityOwner; var contextData = new RequestContextData(RequestContext.GetContext()); contextData.Identity = new ReadiNow.Security.IdentityInfo(wfOwner.Id, wfOwner.Name); using (CustomContext.SetContext(contextData)) { runner.RunWorkflowAsync(new WorkflowStartEvent(workflow) { Arguments = input }); } }
/// <summary> /// Executes the filter action asynchronously. /// </summary> /// <param name="actionContext">The action context.</param> /// <param name="cancellationToken">The cancellation token assigned for this task.</param> /// <param name="continuation">The delegate function to continue after the action method is invoked.</param> /// <returns> /// The newly created task for this operation. /// </returns> public Task <HttpResponseMessage> ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func <Task <HttpResponseMessage> > continuation) { // Get web context string entryPoint = "Failed"; try { entryPoint = actionContext.ControllerContext.Controller.GetType( ).Name + "." + actionContext.ActionDescriptor.ActionName; } catch { } using (DatabaseContextInfo.SetContextInfo($"WebApi - {actionContext.ControllerContext.ControllerDescriptor.ControllerName}.{actionContext.ActionDescriptor.ActionName}")) using (EntryPointContext.SetEntryPoint(entryPoint)) { ProcessMonitorWriter.Instance.Write(entryPoint); RequestContext requestContext = RequestContext.GetContext( ); if (requestContext != null && requestContext.IsValid) { // Attach timezone string tz = HttpContext.Current.Request.Headers.Get("Tz"); if (!string.IsNullOrEmpty(tz)) { // Set the timezone in the logical context var contextData = new RequestContextData(requestContext.Identity, requestContext.Tenant, requestContext.Culture, tz); RequestContext.SetContext(contextData); } } // Do the actual API call work return(continuation( )); } }
public void Test_DateTypes(string fieldTypeAlias, string calculation, string fieldValue, string expectValue) { var curContext = RequestContext.GetContext(); var newContext = new RequestContextData(curContext.Identity, curContext.Tenant, curContext.Culture, "Australia/Sydney"); RequestContext.SetContext(newContext); try { DateTime value = DateTime.ParseExact(fieldValue + ".0000000Z", "o", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal); DateTime expected = DateTime.ParseExact(expectValue + ".0000000Z", "o", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal); Assert.That(value.Kind, Is.EqualTo(DateTimeKind.Utc), "Test sanity check"); var scenario = CreateScenario(fieldTypeAlias, "[Field]", value); var field = scenario.Item1; var inst = scenario.Item2; // Get calculated field DateTime result = (DateTime)inst.GetField(field.Id); Assert.That(result, Is.EqualTo(expected)); Assert.That(result.Kind, Is.EqualTo(DateTimeKind.Utc)); } finally { RequestContext.SetContext(curContext); } }
/// <summary> /// Authenticates the specified user name and password and returns the set of authorization policies for <see cref="T:System.IdentityModel.Tokens.UserNameSecurityToken"/> security tokens. /// </summary> /// <param name="userName">The user name associated with the security token.</param> /// <param name="password">The password associated with the security token.</param> /// <returns> /// A <see cref="T:System.Collections.ObjectModel.ReadOnlyCollection`1"/> of type <see cref="T:System.IdentityModel.Policy.IAuthorizationPolicy"/> that contains the set of authorization policies in effect for this application. /// </returns> /// <exception cref="T:System.ArgumentNullException"> /// <paramref name="userName"/> is null.</exception> /// /// <exception cref="T:System.IdentityModel.Tokens.SecurityTokenValidationException"> /// <paramref name="userName"/> and <paramref name="password"/> combination are not valid.</exception> protected override ReadOnlyCollection <IAuthorizationPolicy> ValidateUserNamePasswordCore(string userName, string password) { ReadOnlyCollection <IAuthorizationPolicy> currentPolicies = base.ValidateUserNamePasswordCore(userName, password); List <IAuthorizationPolicy> newPolicies = new List <IAuthorizationPolicy>(currentPolicies); string tenant = string.Empty; // Split the tenant and username fields string[] credentials = userName.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); if (credentials.Length > 1) { tenant = credentials[0]; userName = credentials[1]; } // Validate the user name and password RequestContextData contextData = UserAccountCache.GetRequestContext(userName, password, tenant); if (contextData == null) { throw new SecurityTokenValidationException("Invalid username and/or password."); } // Extend the original context with culture information newPolicies.Add(new IdentityTenantAuthorizationPolicy(contextData.Identity, contextData.Tenant)); return(newPolicies.AsReadOnly()); }
/// <summary> /// Impersonate an admin of this tenant and return the context object, which must be disposed. /// </summary> public IDisposable GetTenantAdminContext( ) { if (TenantAdminIdentityInfo == null) { using (GetSystemAdminContext( )) { Role role = Entity.Get <Role>("core:administratorRole"); UserAccount userAccount = role.RoleMembers.FirstOrDefault( ); if (userAccount == null) { throw new Exception($"Tenant '{TenantName}' has no administrator."); } TenantAdminIdentityInfo = new IdentityInfo(userAccount.Id, userAccount.Name); } } // Set context var tenantInfo = new EDC.ReadiNow.Metadata.Tenants.TenantInfo(TenantId); RequestContextData contextData = new RequestContextData(TenantAdminIdentityInfo, tenantInfo, CultureHelper.GetUiThreadCulture(CultureType.Neutral)); RequestContext.SetContext(contextData); // Return delegate to revoke context return(ContextHelper.Create(RequestContext.FreeContext)); }
public RunState(WorkflowMetadata metaData, WorkflowRun workflowRun, RequestContextData effectiveSecurityContext) : base(metaData, workflowRun, effectiveSecurityContext) { ownerAccountRuntimeArgName = Entity.GetName(new EntityRef("workflowOwnerAccount").Id); triggeringUserRuntimeArgName = Entity.GetName(new EntityRef("triggeringUserAccount").Id); triggeringPersonRuntimeArgName = Entity.GetName(new EntityRef("triggeringPerson").Id); }
/// <summary> /// Validates the specified user account credentials. /// </summary> /// <param name="username">A string containing the username associated with the user account.</param> /// <param name="password">A string containing the password associated with the user account.</param> /// <param name="tenant">A string containing the tenant associated with the user account.</param> /// <param name="setContext">A Boolean that controls whether or not this method sets the context data within the logical thread for subsequent security checks.</param> /// <remarks>This method does not update any user account information associated with the request.</remarks> public static void Validate(string username, string password, string tenant, bool setContext) { if (string.IsNullOrEmpty(username)) { throw new ArgumentNullException("username"); } if (password == null) { throw new ArgumentNullException("password"); } if (string.IsNullOrEmpty(tenant)) { throw new ArgumentNullException("tenant"); } // Check the credentials RequestContextData contextData = UserAccountCache.GetRequestContext(username, password, tenant); if (contextData == null) { EventLog.Application.WriteWarning(string.Format("Invalid username or password. {0}\\{1} : {2}", tenant, username, (password.Length == 0 ? "blank" : "nonblank"))); throw new InvalidCredentialException(InvalidUserNameOrPasswordMessage); } if (setContext) { // Set the user context data within the logical thread RequestContext.SetContext(contextData); } }
/// <summary> /// Get the request context this workflow will be running as, taking into account triggering user and owner. /// </summary> private RequestContextData GetEffectiveSecurityContext(WorkflowRun run, WorkflowMetadata metaData) { var effectiveUser = GetEffectiveUser(run, metaData); var triggeringUser = GetTriggeringUser(run); // Error! The caller will deal with the missing info. We can't throw becasue RunState is needed for the error reporting if (effectiveUser == null) { return(null); } if (metaData.WfRunAsOwner && metaData.WfSecurityOwner == null) { return(null); } var identityInfo = new IdentityInfo(effectiveUser.Id, effectiveUser.Name); var context = RequestContext.GetContext(); var effectiveSecurityContext = new RequestContextData(context); effectiveSecurityContext.Identity = identityInfo; // If we are running as someone other than the triggerer, set the secondary identity to the triggerer. // NOTE: This could potentially cause a problem in the case where a wf triggering another wf scenario. // It's possible that the user will see stale data. The risk should be quite low. if (triggeringUser != null && triggeringUser.Id != effectiveUser.Id) { effectiveSecurityContext.SecondaryIdentity = new IdentityInfo(triggeringUser.Id, triggeringUser.Name); } return(effectiveSecurityContext); }
/// <summary> /// Constructor /// </summary> /// <param name="requestContextData"></param> /// <param name="accountStatus"></param> public IdentityProviderContextCacheValue(RequestContextData requestContextData, long accountStatus) { if (requestContextData == null) { throw new ArgumentNullException(nameof(requestContextData)); } RequestContextData = requestContextData; AccountStatus = accountStatus; }
/// <summary> /// Signs a software platform user into the system using an existing cookie. /// </summary> private HttpResponseMessage <LoginResult> SigninSoftwarePlatformWithCookie() { var userAgent = Request?.Headers?.UserAgent?.ToString(); var context = EDC.ReadiNow.IO.RequestContext.GetContext(); var contextData = new RequestContextData(context.Identity, context.Tenant, CultureHelper.GetUiThreadCulture(CultureType.Specific), context.TimeZone); AuditLogInstance.Get().OnLogon(true, context.Identity.Name, userAgent); return(new HttpResponseMessage <LoginResult>(GetSuccessfulLoginResult(contextData, context.Identity.Id), HttpStatusCode.OK)); }
public override void QueueAction(Action action) { var contextData = new RequestContextData(RequestContext.GetContext()); _queue.Enqueue(() => { using (CustomContext.SetContext(contextData)) { action(); } }); }
public ActionResult Create(CreateArticleModel createArticleModel) { RequestContextData requestContextData = this.RequestContextData; IApplicationDataCache applicationDataCache = InstanceContainer.ApplicationDataCache; List <IWikiLanguageThreadLookupItem> wikiLanguageThreadLookupItems = applicationDataCache.GetWikiLanguageThreadIdLookup(requestContextData.ApplicationThemeInfo.ApplicationName); return(View(new CreateArticleModel( 5 , new SelectList(wikiLanguageThreadLookupItems, "ArticleGroupThreadId", "LanguageName") ))); }
public RunStateBase(WorkflowMetadata metaData, WorkflowRun _workflowRun, RequestContextData effectiveSecurityContext) : this(metaData) { WorkflowInvoker = new WorkflowInvoker(); WorkflowRun = _workflowRun; StepsTakenInSession = 0; EffectiveSecurityContext = effectiveSecurityContext; ExitPointId = _workflowRun.WorkflowRunExitPoint; HasTimeout = _workflowRun.HasTimeout ?? false; PendingActivity = _workflowRun.PendingActivity; RunStatus = _workflowRun.WorkflowRunStatus_Enum; CompletedAt = _workflowRun.RunCompletedAt; }
/// <summary> /// Start running a task asynchronously. /// </summary> /// <param name="action">The action to execute.</param> /// <param name="settings"></param> public void Start(Action action, AsyncRunnerSettings settings = null) { var context = RequestContext.GetContext( ); var contextData = new RequestContextData(context); Action wrappedAction = () => { using (CustomContext.SetContext(contextData)) { action( ); } }; ThreadPool.QueueUserWorkItem(StartThread, wrappedAction); }
/// <summary> /// Initializes a new instance of the <see cref="OpenIdConnectRequestContextResult" /> class. /// </summary> /// <param name="requestContextData">The request context data.</param> /// <param name="identityProviderUserName">Name of the identity provider user.</param> /// <exception cref="System.ArgumentNullException"> /// </exception> public OpenIdConnectRequestContextResult(RequestContextData requestContextData, string identityProviderUserName) { if (requestContextData == null) { throw new ArgumentNullException(nameof(requestContextData)); } if (string.IsNullOrWhiteSpace(identityProviderUserName)) { throw new ArgumentNullException(nameof(identityProviderUserName)); } RequestContextData = requestContextData; IdentityProviderUserName = identityProviderUserName; }
/// <summary> /// Run a action in the background /// </summary> /// <param name="action"></param> public virtual void QueueAction(Action action) { var contextData = new RequestContextData(RequestContext.GetContext()); var wfRunContext = WorkflowRunContext.Current; Action wrappedAction = () => { using (CustomContext.SetContext(contextData)) using (new WorkflowRunContext(wfRunContext)) { action(); } }; ThreadPool.QueueUserWorkItem(StartThread, wrappedAction); }
/// <summary> /// Gets the successful login result. /// </summary> /// <returns></returns> private static LoginResult GetSuccessfulLoginResult(RequestContextData requestContextData, long accountId = -1) { ///// // Construct the initial settings. ///// var loginResult = new LoginResult { InitialSettings = new InitialSettings { PlatformVersion = SystemInfo.PlatformVersion, RequiredClientVersion = GetRequiredClientVersion(), BranchName = SystemInfo.BranchName, Culture = requestContextData.Culture, FeatureSwitches = Factory.FeatureSwitch.GetFeatureListString() } }; if (accountId != -1) { loginResult.ActiveAccountInfo = new ActiveAccountInfo { AccountId = accountId, }; if (requestContextData != null) { loginResult.ActiveAccountInfo.Tenant = requestContextData.Tenant.Name; loginResult.ActiveAccountInfo.Username = requestContextData.Identity.Name; loginResult.ActiveAccountInfo.Provider = requestContextData.Identity.IdentityProviderTypeAlias; loginResult.ConsoleTimeoutMinutes = LoginConstants.Cookie.Timeout; if (requestContextData.Identity.IdentityProviderId != WellKnownAliases.CurrentTenant.ReadiNowIdentityProviderInstance) { // Ensure we keep the cookie alive for non native identity providers loginResult.ConsoleTimeoutMinutes /= 2; } } // This is only set during integration tests loginResult.TestToken = TestAuthorization.IsEnabled ? TestAuthorization.Instance.GetTestToken(requestContextData.Tenant.Id, WellKnownAliases.CurrentTenant.ReadiNowIdentityProviderInstance, requestContextData.Identity.Name) : null; } return(loginResult); }
public void LogEntryContainsSecondaryName(string secondaryName, string expected) { var toDelete = new List <long>(); try { var policy = new RecordChangeAuditPolicy() { Name = "TEST ResourceAuditEventHandlerTests LogCreate1", TriggeredOnType = Person.Person_Type, TriggerEnabled = true }; policy.UpdatedFieldsToTriggerOn.Add(Resource.Name_Field.As <Field>()); policy.Save(); toDelete.Add(policy.Id); var person = Entity.Create <Person>(); person.Name = "bob"; person.Save(); var log = RunAndLog(() => { var contextData = new RequestContextData(RequestContext.GetContext()); if (secondaryName != null) { contextData.SecondaryIdentity = new IdentityInfo(999, secondaryName); } RequestContext.SetContext(contextData); person = person.AsWritable <Person>(); person.Name = "jane"; person.Save(); }); Assert.That(log.Count, Is.EqualTo(1)); Assert.That(log[0].Name, Is.EqualTo(expected)); } finally { Entity.Delete(toDelete); } }
public void SuspendWithNoSecondaryId() { var oldContext = new RequestContextData(RequestContext.GetContext()); try { var mockHandler = new Mock <DummyHandler>(); var handler = new DummyHandler(); var bgTask = handler.ToBackgroundTask(new DummyParams() { S = "SuspendRestore" }); var primaryUa = new UserAccount() { Name = "primaryId" }; var primaryId = new IdentityInfo(primaryUa.Id, primaryUa.Name); var contextData = new RequestContextData(primaryId, RequestContext.GetContext().Tenant, "XYZ", null) { TimeZone = "XYZTZ" }; RequestContext.SetContext(contextData); using (new SecurityBypassContext()) { // Suspend IEntity suspendedtask = handler.CreateSuspendedTask(bgTask); } } finally { RequestContext.SetContext(oldContext); } }
public IHttpHandler GetHttpHandler(RequestContext requestContext) { // TODO (Roman): errorhandling, cleanup, upper/lower case stuff RequestContextData requestContextData = InstanceContainer.RequestHelper.GetRequestContextData(requestContext.HttpContext.Request); IApplicationContext applicationContext = InstanceContainer.ApplicationContext; IThemeFolderLookup themeFolderLookup = applicationContext.GetThemeFolderLookup(requestContextData.ApplicationThemeInfo.ApplicationGroup); IStaticContentLookup staticContentLookup = applicationContext.GetStaticContentLookup(requestContextData.ApplicationThemeInfo.ApplicationGroup); string text = ContentFormatUtility.Format( requestContextData.Theme , staticContentLookup.GetContent(requestContextData.Theme, "js_globals") , staticContentLookup , themeFolderLookup , ContentFormatUtility.FormatMode.EscapeSingleQuotes); requestContext.HttpContext.Response.Clear(); requestContext.HttpContext.Response.Write(text); requestContext.HttpContext.Response.End(); return(null); }
/// <summary> /// Indicates whether the specified control is authorized. /// </summary> /// <param name="actionContext">The context.</param> /// <returns> /// true if the control is authorized; otherwise, false. /// </returns> protected override bool IsAuthorized(HttpActionContext actionContext) { if (actionContext == null || actionContext.Request == null) { // This is intentionally an ArgumentNullException instead of a WebArgumentNullException because // this should never be called with a null actionContext by ASP.NET WebAPI. throw new ArgumentNullException("actionContext"); } // // Integration Test Authorization // if we are in integrated testing mode and a test token has been provided, use it. If it fails, pretend it never happened. // Otherwise perform a normal test. // if (TestAuthorization.IsEnabled) { var authorizationHeader = HttpContext.Current.Request.Headers.Get("Authorization"); if (!string.IsNullOrEmpty(authorizationHeader)) { long tenantId; long providerId; string userName; if (TestAuthorization.Instance.TryGetIdentifier(authorizationHeader, out tenantId, out providerId, out userName)) { var testRequestContextData = Factory.IdentityProviderRequestContextCache.GetRequestContextData(tenantId, providerId, userName, false); RequestContext.SetContext(testRequestContextData); return(true); } } // fall back to usual login } Collection <CookieHeaderValue> cookies = actionContext.Request.Headers.GetCookies( ); // // Normal authorization // CookieState aspxAuthCookie = cookies.Select(c => c[FormsAuthentication.FormsCookieName]).FirstOrDefault( ); if (aspxAuthCookie == null) { throw new InvalidCredentialException(AuthenticationCookieMissingMessage); } string ticketData = aspxAuthCookie.Value; if (string.IsNullOrEmpty(ticketData)) { throw new InvalidCredentialException(AuthenticationCookieInvalidMessage); } FormsAuthenticationTicket authenticationTicket; try { authenticationTicket = FormsAuthentication.Decrypt(ticketData); } catch (Exception ex) { EventLog.Application.WriteError("Error decrypting authentication ticket. " + ex.Message); throw new InvalidCredentialException(UserAccountValidator.InvalidUserNameOrPasswordMessage, ex); } if (authenticationTicket == null) { throw new InvalidCredentialException(UserAccountValidator.InvalidUserNameOrPasswordMessage); } ///// // Check whether the ticket has expired. ///// if (authenticationTicket.Expired) { throw new AuthenticationTokenExpiredException( ); } // Get the encrypted cookie payload AuthenticationToken authTicket; try { using (var input = new StringReader(authenticationTicket.UserData)) { authTicket = JSON.Deserialize <AuthenticationToken>(input); } } catch (Exception ex) { throw new InvalidCredentialException(AuthenticationCookieInvalidMessage, ex); } if (authTicket == null) { throw new InvalidCredentialException(AuthenticationCookieInvalidMessage); } // Prevent XSRF attacks bool noXsrfCheck = actionContext.ActionDescriptor.GetCustomAttributes <NoXsrfCheckAttribute>( ).Count > 0 || actionContext.ActionDescriptor.ControllerDescriptor.GetCustomAttributes <NoXsrfCheckAttribute>( ).Count > 0; if (!noXsrfCheck && !CookieHelper.VerifyXsrfToken(actionContext, authTicket, cookies)) { EventLog.Application.WriteWarning($"Invalid XSRF token detected. Headers:\n{actionContext?.Request?.Headers}"); throw new XsrfValidationException( ); } RequestContextData requestContextData = Factory.IdentityProviderRequestContextCache.GetRequestContextData(authTicket.TenantId, authTicket.IdentityProviderId, authTicket.IdentityProviderUserName, false); if (requestContextData == null) { throw new InvalidCredentialException(UserAccountValidator.InvalidUserNameOrPasswordMessage); } if (authTicket.UserAccountId != requestContextData.Identity.Id) { throw new InvalidCredentialException(UserAccountValidator.InvalidUserNameOrPasswordMessage); } RequestContext.SetContext(requestContextData); ///// // Don't extend the cookie timeout for challenge requests for the native identity provider ///// if (actionContext.Request.RequestUri.LocalPath.ToLowerInvariant() == ChallengeRequestUri && authTicket.IdentityProviderId == WellKnownAliases.CurrentTenant.ReadiNowIdentityProviderInstance) { return(true); } ///// // Sliding window expiry. // Note* If the Web page is accessed before half of the expiration time passes, the ticket expiration // time will not be reset. As per http://support.microsoft.com/kb/910443/en-gb ///// if (DateTime.Now <= authenticationTicket.Expiration.AddMinutes(-(LoginConstants.Cookie.Timeout / 2))) { return(true); } ///// // Do not require the caller to have access to the authentication entities e.g. Open ID provider. ///// using (new SecurityBypassContext( )) { CookieHelper.CreateAuthenticationAndXsrfCookies(authTicket.TenantId, authTicket.IdentityProviderId, authTicket.IdentityProviderUserName, authTicket.UserAccountId, authTicket.Persist, authTicket.XsrfToken); } return(true); }
/// <summary> /// Checks the credentials for the specified user account. /// </summary> /// <param name="username">A string containing the username associated with the user account. This cannot be null or empty.</param> /// <param name="password">A string containing the password associated with the user account. This cannot be null.</param> /// <param name="tenantName">Name of the tenant. This cannot be null or empty.</param> /// <param name="updateAccount">A Boolean value that controls whether or not user account information associated with the request is updated.</param> /// <param name="skipPasswordExpiryCheck">A Boolean that controls whether to perform the password expiry check.</param> /// <returns>An object representing the identity of the user account</returns> /// <exception cref="ArgumentException"> /// The given account details are incorrect. /// </exception> /// <exception cref="TenantDisabledException"> /// The tenant is disabled, meaning no user in that tenant can authenticate. /// </exception> private static RequestContextData ValidateAccount(string username, string password, string tenantName, bool updateAccount, bool skipPasswordExpiryCheck = false) { if (String.IsNullOrEmpty(username)) { throw new ArgumentException("The specified username parameter is invalid."); } if (password == null) { throw new ArgumentNullException("password"); } if (String.IsNullOrEmpty(tenantName)) { throw new ArgumentException("The specified tenant parameter is invalid."); } RequestContextData contextData; // Cache the original request context RequestContext originalContextData = RequestContext.GetContext( ); try { TenantInfo tenantInfo; UserAccount userAccount; PasswordPolicy passwordPolicy; // Set the system administrators context RequestContext.SetSystemAdministratorContext( ); try { if (password.Length > MaxPasswordLength) { throw new ArgumentException( string.Format("Password cannot be longer than {0} characters", MaxPasswordLength), "password"); } if (tenantName == SpecialStrings.GlobalTenant) { // Create a Dummy Tenant Info // No need to set the context as we are already the global admin tenantInfo = new TenantInfo(0) { Name = SpecialStrings.GlobalTenant }; } else { // Get the tenant with the specified name Tenant tenant = TenantHelper.Find(tenantName); if (tenant == null) { throw new ArgumentException(string.Format("Unknown tenant '{0}'", tenantName), "tenantName"); } if (tenant.IsTenantDisabled ?? false) { throw new TenantDisabledException(tenantName); } // Set the tenant administrators context RequestContext.SetTenantAdministratorContext(tenant.Id); tenantInfo = new TenantInfo(tenant.Id) { Name = tenantName.ToUpperInvariant() }; } // Get the user account with the specified name userAccount = Entity.GetByField <UserAccount>(username, true, new EntityRef("core", "name")).FirstOrDefault( ); if (userAccount == null) { throw new ArgumentException(string.Format("Could not find user '{0}' in tenant '{1}'", username, tenantName)); } // Get the password policy passwordPolicy = Entity.Get <PasswordPolicy>(new EntityRef("core:passwordPolicyInstance")); if (passwordPolicy == null) { throw new ArgumentException(string.Format("Could not find password policy for tenant '{0}'", tenantName)); } } catch (Exception ex) { EventLog.Application.WriteWarning("Login failed: " + ex.Message); // Validate a password here to mitigate timing attacks. An attacker could use this // to guess which passwords are valid by timing the login. Without this, logins that // have a invalid user name and tenant will be quicker than those with a valid user name. CryptoHelper.CreateEncodedSaltedHash("test password"); throw; } ValidateAccount(userAccount, passwordPolicy, password, updateAccount, skipPasswordExpiryCheck); // Set the context data var identityInfo = new IdentityInfo(userAccount.Id, userAccount.Name); contextData = new RequestContextData(identityInfo, tenantInfo, CultureHelper.GetUiThreadCulture(CultureType.Specific)); } finally { // Restore the original request context if ((originalContextData != null) && (originalContextData.IsValid)) { RequestContext.SetContext(originalContextData); } } return(contextData); }
public HttpResponseMessage <string> Feedback([FromBody] FeedbackData data) { if (data == null) { throw new ArgumentNullException("data"); } var idString = Guid.NewGuid().ToString(); var text = ""; // Aggregate for some misguided reason throws if the collection is empty if (data.Messsages.Count > 0) { text = data.Messsages.Aggregate((a, p) => a + (string.IsNullOrEmpty(a) ? "" : "\r\n") + p); } var context = new RequestContextData(EDC.ReadiNow.IO.RequestContext.GetContext()); if (context == null || context.Identity == null || context.Tenant == null) { throw new InvalidOperationException("Failed to determine identity"); } string tenantName = context.Tenant.Name; string userName = context.Identity.Name; var e = ReadiNow.Model.Entity.Get <UserAccount>(context.Identity.Id); if (e == null) { throw new InvalidOperationException("Failed to determine account holder"); } string personName = e.AccountHolder != null ? e.AccountHolder.Name : context.Identity.Name; var path = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData); path = Path.Combine(path, @"ReadiNow\ClientLogs"); //todo- factor out that clean routine... just can't remember a quick way in C#.... path = Path.Combine(path, Regex.Replace(tenantName, @"[^A-Za-z0-9_]+", "-")); path = Path.Combine(path, Regex.Replace(userName, @"[^A-Za-z0-9_]+", "-")); path = Path.Combine(path, idString); Directory.CreateDirectory(path); Directory.CreateDirectory(Path.Combine(path, "attachments")); using (var fs = new FileStream(Path.Combine(path, "comments.txt"), FileMode.Create)) using (var w = new StreamWriter(fs)) { w.Write(data.Comments); w.Close(); } using (var fs = new FileStream(Path.Combine(path, "browser.log"), FileMode.Create)) using (var w = new StreamWriter(fs)) { w.Write(text); w.Close(); } if (data.Attachments != null) // am so over null checks.... foreach throws { foreach (var a in data.Attachments) { // strip off things like data:text/plain;base64, if (Regex.IsMatch(a.Data, "^data:.*;base64,")) { a.Data = a.Data.Substring(a.Data.IndexOf(',') + 1); } using (var fs = new FileStream(Path.Combine(path, "attachments", a.Name + "." + a.Ext), FileMode.Create)) using (var bw = new BinaryWriter(fs)) { var content = Convert.FromBase64String(a.Data); bw.Write(content); bw.Close(); } } } SaveRecentServerLogs(path); ReadiNow.Diagnostics.EventLog.Application.WriteInformation("Client feedback saved to {0}", path); // if configured to create a ticket in ReadiDesk then do so var description = ""; description += "email: " + data.Email + "\n"; description += "phone: " + data.Phone + "\n"; description += "tenant: " + tenantName + "\n"; description += "account: " + userName + "\n"; description += "user: "******"\n"; description += "front end server: " + Dns.GetHostEntry("localhost").HostName + "\n"; description += "platform version: " + SystemInfo.PlatformVersion + "\n"; description += "branch name: " + SystemInfo.BranchName + "\n"; var apps = ReadiNow.Model.Entity.GetInstancesOfType <Solution>(); var appList = apps.Aggregate("", (a, p) => a + (string.IsNullOrEmpty(a) ? "" : ", ") + p.Name + " (" + p.SolutionVersionString + ")"); description += "apps: " + appList + "\n"; description += "\ndetails: " + data.Comments + "\n\n"; var ticket = new ReadiDeskTicket { TenantName = tenantName, UserName = userName, Summary = data.Comments.Split('\n').FirstOrDefault(), Description = description, Attachments = new List <Attachment>() { new Attachment { Name = "consolelog", Ext = "txt", Data = Convert.ToBase64String(Encoding.UTF8.GetBytes(text)) } } }; ticket.Summary = GetSanitizedNameFieldValue(ticket.Summary); // ticket summary is saved as the name of the ticket if (data?.Attachments != null) { ticket.Attachments = ticket.Attachments.Concat(data.Attachments).ToList( ); } idString = ReadiDeskService.RemoteCreateTicket(ticket) ?? idString; return(new HttpResponseMessage <string>(idString, HttpStatusCode.OK)); }
protected override void Execute(IJobExecutionContext jobContext) { var stopWatch = new Stopwatch(); perfCounters.GetPerformanceCounter <RatePerSecond32PerformanceCounter>(WorkflowPerformanceCounters.ScheduleFireRateCounterName).Increment(); stopWatch.Start(); var jobRef = ScheduledItemHelper.GetScheduledItemRef(jobContext); Diagnostics.EventLog.Application.WriteTrace($"Starting job {jobRef.Id}."); try { using (DeferredChannelMessageContext deferredMsgContext = new DeferredChannelMessageContext()) // needed to keep redis happy { // Set the context to the owner of the scheduled item. var scheduledItem = Entity.Get <ScheduledItem>(jobRef); if (scheduledItem == null) { Diagnostics.EventLog.Application.WriteTrace($"Attempted to start a job which references a nonexistant item. Ignoring. JobContext: {jobContext.ToString()}"); return; } if (RunAsOwner) { var owner = scheduledItem.SecurityOwner; if (owner == null) { var message = $"Unable to start scheduled job as import configuration has no owner"; Diagnostics.EventLog.Application.WriteError($"StartImportJob.Execute: {message}. {scheduledItem.Id}"); throw GenerateJobException(message, scheduledItem); } var identityInfo = new IdentityInfo(owner.Id, owner.Name); var contextData = new RequestContextData(RequestContext.GetContext()); contextData.Identity = identityInfo; using (CustomContext.SetContext(contextData)) { Execute(jobRef); } } else { Execute(jobRef); } } } catch (JobExecutionException ex) { EDC.ReadiNow.Diagnostics.EventLog.Application.WriteTrace("Job execution exception. Ex: {0}", ex.ToString()); throw; // The job has already handled the problem and taken action. } catch (PlatformSecurityException ex) { Diagnostics.EventLog.Application.WriteError($"Platform security exception thrown to scheduler. This should never occur. Ex: {ex}"); } catch (Exception ex) { Diagnostics.EventLog.Application.WriteError("Exception thrown to scheduler. This should never occur and should be handled by the scheduled item. Ex: {0}", ex.ToString()); } stopWatch.Stop(); perfCounters.GetPerformanceCounter <AverageTimer32PerformanceCounter>(WorkflowPerformanceCounters.ScheduleJobDurationCounterName).AddTiming(stopWatch); }
/// <summary> /// Executed before the message is saved /// </summary> /// <param name="message"></param> /// <param name="postSaveAction">if not null an action run after the save. This happens even if the save is cancelled.</param> /// <returns> /// True if the save is to be cancelled /// </returns> public bool BeforeSave(ReceivedEmailMessage message, out Action postSaveAction) { postSaveAction = null; ///// // Check the message. ///// if (message == null) { return(false); } var iCalMessage = message.As <ReceivedICalEmailMessage>( ); ///// // Ensure the message is a received iCal email message. ///// if (iCalMessage == null) { return(false); } ///// // The iCalUpdate field was set by the iCalMailMesssageFormatter that was called as part // of the ProcessInboxes action. ///// if (string.IsNullOrEmpty(iCalMessage.ICalUpdate)) { return(false); } ///// // Read the iCal update. ///// using (var sr = new StringReader(iCalMessage.ICalUpdate)) { ///// // Deserialize the string into the iCal object model. ///// IICalendarCollection iCalendarCollection = iCalendar.LoadFromStream(sr); if (iCalendarCollection == null) { return(false); } ///// // Get the first calendar. ///// IICalendar calendar = iCalendarCollection.FirstOrDefault( ); if (calendar == null || calendar.Events == null) { return(false); } ///// // Get the first calendar event. ///// IEvent calendarEvent = calendar.Events.FirstOrDefault( ); if (calendarEvent == null) { return(false); } ///// // Make sure the calendar events UID is set. ///// if (string.IsNullOrEmpty(calendarEvent.Uid)) { return(false); } EventEmail eventEntity = null; Appointment appointment = null; ///// // Find all sent iCal UID containers that correlate to the received calendar events UID. ///// IEnumerable <ICalUidContainer> iCalUidContainers = Entity.GetByField <ICalUidContainer>(calendarEvent.Uid, ICalUidContainer.ICalUid_Field); if (iCalUidContainers != null) { ///// // Get the first sent message. ///// ICalUidContainer iCalUidContainer = iCalUidContainers.FirstOrDefault( ); if (iCalUidContainer != null && iCalUidContainer.CalendarEventEmail != null) { ///// // Get the original event email object that was used to create the sent iCal Email Message. ///// eventEntity = iCalUidContainer.CalendarEventEmail.AsWritable <EventEmail>( ); } } bool modificationsMade = false; if (eventEntity == null) { ///// // No existing event email so this is a new request. ///// EntityRef type = GetEventCreationType(message); eventEntity = type != null?Entity.Create(type).As <EventEmail>( ) : new EventEmail( ); appointment = Entity.Create <Appointment>(); eventEntity.EventEmailAppt = appointment; modificationsMade = true; eventEntity.Name = calendarEvent.Summary; var calUidContainer = new ICalUidContainer { ICalUid = calendarEvent.Uid }; eventEntity.CalendarId = calUidContainer; string creatorEmailAddress = GetEmailAddress(message.EmFrom); if (creatorEmailAddress != null) { EmailContact creatorEmailContact = FindEmailContact(creatorEmailAddress); if (creatorEmailContact == null) { var mailAddress = new MailAddress(message.EmFrom); creatorEmailContact = CreateEmailContact(creatorEmailAddress, mailAddress.DisplayName ?? creatorEmailAddress); } eventEntity.EventEmailCreator = creatorEmailContact; } foreach (IAttendee attendee in calendarEvent.Attendees) { string emailAddress = GetEmailAddress(attendee.Value.ToString( )); if (emailAddress != null) { EmailContact emailContact = FindEmailContact(emailAddress); if (emailContact == null) { CreateEmailContact(emailAddress, attendee.CommonName); } appointment.EventEmailAttendees.Add(emailContact.EmailContactOwner); } } CreateAndSendAcceptance(calendar, iCalMessage, eventEntity); } else { appointment = eventEntity.EventEmailAppt; if (calendar.Method == Methods.Publish || calendar.Method == Methods.Request) { ///// // A REQUEST or PUBLISH means a new event arriving in the system. ///// CreateAndSendAcceptance(calendar, iCalMessage, eventEntity); } } eventEntity.ReceivedEmailMessages.Add(iCalMessage); ///// // Start time. ///// if (calendarEvent.Start != null) { DateTime utcTime = calendarEvent.Start.Utc; if (!Equals(utcTime, appointment.EventStart)) { appointment.EventStart = utcTime; modificationsMade = true; } } ///// // End time. ///// if (calendarEvent.End != null) { DateTime utcTime = calendarEvent.End.Utc; if (!Equals(utcTime, appointment.EventEnd)) { appointment.EventEnd = utcTime; modificationsMade = true; } } ///// // All Day Event. ///// if (appointment.EventIsAllDay == null || !Equals(calendarEvent.IsAllDay, appointment.EventIsAllDay.Value)) { appointment.EventIsAllDay = calendarEvent.IsAllDay; modificationsMade = true; } ///// // Location. ///// if (calendarEvent.Location != null) { if (!Equals(calendarEvent.Location, appointment.EventLocation)) { appointment.EventLocation = calendarEvent.Location; modificationsMade = true; } } ///// // Location. ///// if (eventEntity.EventEmailAppt.EventEmailPriority == null || !Equals(calendarEvent.Priority, eventEntity.EventEmailAppt.EventEmailPriority)) { string priorityAlias; if (calendarEvent.Priority <= 0) { ///// // Undefined. ///// priorityAlias = null; } else if (calendarEvent.Priority <= 4) { ///// // High priority. ///// priorityAlias = "core:highPriority"; } else if (calendarEvent.Priority == 5) { ///// // Normal priority. ///// priorityAlias = "core:normalPriority"; } else if (calendarEvent.Priority <= 9) { ///// // Low priority. ///// priorityAlias = "core:lowPriority"; } else { ///// // Invalid priority. ///// priorityAlias = null; } eventEntity.EventEmailAppt.EventEmailPriority = priorityAlias != null?Entity.Get <EventEmailPriorityEnum>(priorityAlias) : null; modificationsMade = true; } ///// // Status. ///// string statusAlias = null; switch (calendarEvent.Status) { case EventStatus.Cancelled: statusAlias = "core:eventStatusCancelled"; break; case EventStatus.Confirmed: statusAlias = "core:eventStatusConfirmed"; break; case EventStatus.Tentative: statusAlias = "core:eventStatusTentative"; break; } if (!string.IsNullOrEmpty(statusAlias)) { if (appointment.EventStatus == null || appointment.EventStatus.Alias != statusAlias) { appointment.EventStatus = Entity.Get <EventStatusEnum>(statusAlias); modificationsMade = true; } } if (modificationsMade) { CustomContext cc = null; try { string timeZone = null; if (eventEntity != null) { ///// // Find all sent iCal Email Messages that correlate to the received calendar events UID. ///// IEnumerable <SentICalEmailMessage> sentICalEmailMessages = eventEntity.SentEmailMessages; if (sentICalEmailMessages != null) { SentICalEmailMessage sentICalEmailMessage = sentICalEmailMessages.FirstOrDefault(sent => sent.ICalTimeZone != null); if (sentICalEmailMessage != null) { timeZone = sentICalEmailMessage.ICalTimeZone; } } } if (string.IsNullOrEmpty(timeZone)) { if (calendar.TimeZones != null) { ITimeZone calendarTimeZone = calendar.TimeZones.FirstOrDefault( ); if (calendarTimeZone != null) { timeZone = calendarTimeZone.TzId; } } } if (!string.IsNullOrEmpty(timeZone)) { ///// // Set up a custom context just for the duration of this call. ///// RequestContext currentRequestContext = RequestContext.GetContext( ); var data = new RequestContextData(currentRequestContext) { TimeZone = timeZone }; cc = new CustomContext(data); } eventEntity.Save( ); } finally { ///// // Ensure the custom context is disposed. ///// if (cc != null) { cc.Dispose( ); } } } } return(false); }
/// <summary> /// Sets the request context data associated with the service request. /// </summary> internal static void SetRequestContextData(RequestContextData contextData) { AppRequestContext.SetContext(contextData); }
public void SuspendRestore() { var mockHandler = new Mock <DummyHandler>(); var handler = new DummyHandler(); var primaryUa = new UserAccount() { Name = Guid.NewGuid().ToString() }; primaryUa.Save(); var secondaryUa = new UserAccount() { Name = Guid.NewGuid().ToString() }; secondaryUa.Save(); var primaryId = new IdentityInfo(primaryUa.Id, primaryUa.Name); var secondaryId = new IdentityInfo(secondaryUa.Id, secondaryUa.Name); var contextData = new RequestContextData(primaryId, RequestContext.GetContext().Tenant, "XYZ", secondaryId) { TimeZone = "XYZTZ" }; var oldContext = new RequestContextData(RequestContext.GetContext()); try { RequestContext.SetContext(contextData); using (new SecurityBypassContext()) { // Suspend IEntity suspendedtask; BackgroundTask bgTask; bgTask = handler.ToBackgroundTask(new DummyParams() { S = "SuspendRestore" }); suspendedtask = handler.CreateSuspendedTask(bgTask); suspendedtask.Save(); Assert.That(handler.annotateSuspendedTask_calls, Is.EqualTo(1)); var castTask = suspendedtask.As <SuspendedTask>(); Assert.That(castTask.StCulture, Is.EqualTo("XYZ")); Assert.That(castTask.StTimezone, Is.EqualTo("XYZTZ")); Assert.That(castTask.StIdentity.Id, Is.EqualTo(primaryUa.Id)); Assert.That(castTask.StSecondaryIdentity.Id, Is.EqualTo(secondaryUa.Id)); IEnumerable <BackgroundTask> restoredTasks; //Restore restoredTasks = handler.RestoreSuspendedTasks(); Assert.That(handler.restoreTaskData_Calls, Is.EqualTo(1)); Assert.That(restoredTasks.Count(), Is.EqualTo(1)); var context = restoredTasks.First().Context; Assert.That(context.Culture, Is.EqualTo("XYZ")); Assert.That(context.TimeZone, Is.EqualTo("XYZTZ")); Assert.That(context.Identity.Id, Is.EqualTo(primaryId.Id)); Assert.That(context.SecondaryIdentity.Id, Is.EqualTo(secondaryId.Id)); var parameter = restoredTasks.First().GetData <DummyParams>(); Assert.That(parameter.S, Is.EqualTo("restored")); } } finally { RequestContext.SetContext(oldContext); } }
/// <summary> /// Gets the request context data factory implementation. /// </summary> /// <param name="key">The key.</param> /// <returns>RequestContextData.</returns> private IdentityProviderContextCacheValue GetRequestContextDataFactoryImpl(IdentityProviderContextCacheKey key) { IdentityProviderContextCacheValue cacheValue; var isSystem = key.IdentityProviderId == WellKnownAliases.CurrentTenant.ReadiNowIdentityProviderInstance; QueryBuild queryResult = GetSql(isSystem); using (var dbContext = DatabaseContext.GetContext()) { using (var command = dbContext.CreateCommand(queryResult.Sql)) { command.AddParameterWithValue("@identityProviderUser", key.IdentityProviderUserName, 500); if (!isSystem) { command.AddParameterWithValue("@identityProviderId", key.IdentityProviderId); } dbContext.AddParameter(command, "@tenant", DbType.Int64, key.TenantId); if (queryResult.SharedParameters != null) { foreach (var parameter in queryResult.SharedParameters) { dbContext.AddParameter(command, parameter.Value, parameter.Key.Type, parameter.Key.Value); } } using (var reader = command.ExecuteReader()) { if (!reader.Read()) { return(null); } var userAccountId = reader.GetInt64(0); var userAccountName = reader.GetString(1); var identityProviderId = isSystem ? key.IdentityProviderId : reader.GetInt64(2); var identityProviderUserId = isSystem ? userAccountId : reader.GetInt64(3); var identityProviderTypeAlias = isSystem ? "core:readiNowIdentityProvider" : "core:" + reader.GetString(4); int accountStatusColumnIndex = isSystem ? 2 : 5; long accountStatusId = -1; if (!reader.IsDBNull(accountStatusColumnIndex)) { accountStatusId = reader.GetInt64(accountStatusColumnIndex); } var identityInfo = new IdentityInfo(userAccountId, userAccountName) { IdentityProviderId = identityProviderId, IdentityProviderUserId = identityProviderUserId, IdentityProviderTypeAlias = identityProviderTypeAlias }; var tenantInfo = new TenantInfo(key.TenantId); var contextData = new RequestContextData(identityInfo, tenantInfo, CultureHelper.GetUiThreadCulture(CultureType.Specific)); cacheValue = new IdentityProviderContextCacheValue(contextData, accountStatusId); if (CacheContext.IsSet()) { using (CacheContext cacheContext = CacheContext.GetContext()) { cacheContext.Entities.Add(userAccountId); cacheContext.Entities.Add(identityProviderId); if (identityProviderUserId != userAccountId) { cacheContext.Entities.Add(identityProviderUserId); } } } } } } return(cacheValue); }
/// <summary> /// Sets the request context. /// </summary> private void SetRequestContext( ) { RequestContext context = RequestContext.GetContext( ); if (context != null && context.IsValid && context.Tenant?.Name != null) { if (context.Tenant.Name.Equals(TenantName, StringComparison.OrdinalIgnoreCase)) { ///// // Context already set. ///// return; } } RequestContextData contextData; ///// // See if the request context has been cached. ///// if (!RequestContextCache.TryGetValue(TenantName, out contextData)) { if (TenantName.Equals(SpecialStrings.GlobalTenant)) { var tenantInfo = new TenantInfo(0); var identityInfo = new IdentityInfo(0, SpecialStrings.SystemAdministratorUser); contextData = new RequestContextData(identityInfo, tenantInfo, CultureHelper.GetUiThreadCulture(CultureType.Neutral)); } else { ///// // Set system administrators context to retrieve the tenant. ///// RequestContext.SetSystemAdministratorContext( ); ///// // Retrieve the requested tenant. ///// Tenant tenant = TenantHelper.Find(TenantName); RequestContext.SetTenantAdministratorContext(tenant.Id); UserAccount userAccount = Entity.GetByField <UserAccount>(SpecialStrings.SystemAdministratorUser, false, new EntityRef("core", "name")).FirstOrDefault() ?? Entity.GetByField <UserAccount>(SpecialStrings.TenantAdministratorUser, false, new EntityRef("core", "name")).FirstOrDefault(); if (userAccount == null) { throw new EntityNotFoundException("The 'Administrator' account for tenant '" + TenantName + "' could not be found."); } ///// // Set the context data ///// var identityInfo = new IdentityInfo(userAccount.Id, userAccount.Name); var tenantInfo = new TenantInfo(tenant.Id); contextData = new RequestContextData(identityInfo, tenantInfo, CultureHelper.GetUiThreadCulture(CultureType.Neutral)); } RequestContextCache[TenantName] = contextData; } RequestContext.SetContext(contextData); }