/// <summary> /// Manual database locking is used here in order to avoid deadlocks (may depend on usage of READ_COMMITTED_SNAPSHOT), /// see integration test AddUnregisteredPrincipalsParallel. /// </summary> /// <remarks> /// Note that lock resource name is case-sensitive in SQL Server. /// </remarks> private CustomLockInfo CreteCustomLock(string userName) { string key = $"AuthorizationDataLoader.{userName}"; key = CsUtility.LimitWithHash(key, 255); // SQL Server limits key length to 255. try { _sqlExecuter.ExecuteSql( $@"DECLARE @lockResult int; EXEC @lockResult = sp_getapplock {SqlUtility.QuoteText(key)}, 'Exclusive'; IF @lockResult < 0 BEGIN RAISERROR('AuthorizationDataLoader lock.', 16, 10); ROLLBACK; RETURN; END"); return(new CustomLockInfo(key)); } catch (FrameworkException ex) when(ex.Message.TrimEnd().EndsWith("AuthorizationDataLoader lock.")) { throw new UserException( "Cannot initialize the new user, because the user record is locked by another command that is still running.", ex); } }
public void GenerateCode(IConceptInfo conceptInfo, ICodeBuilder codeBuilder) { var info = (UniqueReferenceInfo)conceptInfo; if (DslUtility.IsQueryable(info.Extension) && DslUtility.IsQueryable(info.Base)) { DataStructureQueryableCodeGenerator.AddNavigationPropertyWithBackingField(codeBuilder, info.Extension, csPropertyName: "Base", propertyType: "Common.Queryable." + info.Base.Module.Name + "_" + info.Base.Name, additionalSetterCode: "ID = value != null ? value.ID : Guid.Empty;"); DataStructureQueryableCodeGenerator.AddNavigationPropertyWithBackingField(codeBuilder, info.Base, csPropertyName: info.ExtensionPropertyName(), propertyType: "Common.Queryable." + info.Extension.Module.Name + "_" + info.Extension.Name, additionalSetterCode: null); } if (UniqueReferenceDatabaseDefinition.IsSupported(info) && info.Extension is IOrmDataStructure && info.Base is IWritableOrmDataStructure) { var ormDataStructure = (IOrmDataStructure)info.Extension; string systemMessage = $"DataStructure:{info.Extension.FullName},Property:ID,Referenced:{info.Base.FullName}"; string onDeleteInterpretSqlError = @"if (interpretedException is Rhetos.UserException && Rhetos.Utilities.MsSqlUtility.IsReferenceErrorOnDelete(interpretedException, " + CsUtility.QuotedString(ormDataStructure.GetOrmSchema() + "." + ormDataStructure.GetOrmDatabaseObject()) + @", " + CsUtility.QuotedString("ID") + @", " + CsUtility.QuotedString(UniqueReferenceDatabaseDefinition.GetConstraintName(info)) + @")) ((Rhetos.UserException)interpretedException).SystemMessage = " + CsUtility.QuotedString(systemMessage) + @"; "; codeBuilder.InsertCode(onDeleteInterpretSqlError, WritableOrmDataStructureCodeGenerator.OnDatabaseErrorTag, info.Base); } }
/// <summary> /// Returns plugins that are registered for the given interface, sorted by dependencies (MefPovider.DependsOn). /// </summary> internal static IEnumerable <PluginInfo> FindPlugins(ContainerBuilder builder, Type pluginInterface) { lock (_pluginsLock) { if (_pluginsByExport == null) { var assemblies = ListAssemblies(); try { _pluginsByExport = LoadPlugins(assemblies); } catch (Exception ex) { string typeLoadReport = CsUtility.ReportTypeLoadException(ex, "Cannot load plugins.", assemblies); if (typeLoadReport != null) { throw new FrameworkException(typeLoadReport, ex); } else { ExceptionsUtility.Rethrow(ex); } } } return(_pluginsByExport.Get(pluginInterface.FullName)); } }
private static string ImplementationCodeSnippet(RegExMatchInfo info) { return(string.Format(@"[RegularExpression({0}, ErrorMessage = {1})] ", CsUtility.QuotedString(info.RegularExpression), CsUtility.QuotedString(info.ErrorMessage))); }
/// <summary> /// Case-insensitive comparison. /// </summary> public static void AssertContains(string text, IEnumerable <string> patterns, string message = null, string errorContext = null) { CsUtility.Materialize(ref patterns); if (patterns.Any(string.IsNullOrEmpty)) { throw new ArgumentException("Given list of patterns contains an empty string."); } Console.WriteLine("[AssertContains] Text: '" + text + "'."); foreach (var pattern in patterns) { Console.Write("[AssertContains] Looking for pattern '" + pattern + "'."); if (text.ToLower().Contains(pattern.ToLower())) { Console.WriteLine(" Found."); } else { Console.WriteLine(" Not found."); Console.WriteLine(errorContext); Assert.Fail("Text should contain pattern '" + pattern + "'." + (string.IsNullOrEmpty(message) ? " " + message : "") + " " + "The text is '" + text.Limit(200, true) + "'."); } } }
#pragma warning disable S1172 // Unused method parameters should be removed // Parameter "IConfiguration configuration" is not used here in default configuration, // but is allowed as an option for custom configuration implementations. private void DefaultContainerConfiguration(IConfiguration configuration, ContainerBuilder builder, List <Action <ContainerBuilder> > customActions) { builder.AddRhetosRuntime(); builder.AddRhetosPluginModules(); CsUtility.InvokeAll(builder, customActions); }
private IConfiguration BuildConfiguration() { var configurationBuilder = new ConfigurationBuilder(_builderLogProvider); CsUtility.InvokeAll(configurationBuilder, _configureConfigurationActions); return(configurationBuilder.Build()); }
public void GetShortTypeName() { var types = new[] { typeof(int), typeof(string), typeof(InnerClass), typeof(List <int>), typeof(List <string>), typeof(List <InnerClass>), typeof(int[]), typeof(string[]), typeof(InnerClass[]), typeof(Dictionary <List <InnerClass[]>, InnerClass>), }; var results = types.Select(t => CsUtility.GetShortTypeName(t)).ToList(); string expected = @"Int32 String InnerClass List`1<Int32> List`1<String> List`1<InnerClass> Int32[] String[] InnerClass[] Dictionary`2<List`1<InnerClass[]>, InnerClass>"; TestUtility.AssertAreEqualByLine(expected, string.Join("\r\n", results)); }
public void GenerateCode(IConceptInfo conceptInfo, ICodeBuilder codeBuilder) { var info = (QueryInfo)conceptInfo; codeBuilder.InsertCode($"new KeyValuePair<string, Type>({CsUtility.QuotedString(info.Parameter)}, typeof({info.Parameter})),{Environment.NewLine} ", RepositoryHelper.ReadParameterTypesTag, info.DataStructure); }
public IEnumerable <IConceptInfo> CreateNewConcepts(ChangesOnReferencedInfo conceptInfo, IDslModel existingConcepts) { var reference = DslUtility.GetPropertyByPath(conceptInfo.Computation, conceptInfo.ReferencePath, existingConcepts).Value; if (!(reference is ReferencePropertyInfo)) { throw new DslSyntaxException(conceptInfo, $"The given path '{conceptInfo.ReferencePath}' should end with a reference property, instead of the {reference.GetUserDescription()}."); } var referenced = ((ReferencePropertyInfo)reference).Referenced; var computationDependencies = new List <Tuple <DataStructureInfo, string> >(); if (referenced is IWritableOrmDataStructure) { computationDependencies.Add(Tuple.Create(referenced, "item => item.ID")); } else if (referenced is PolymorphicInfo) { AddPolymorphicImplementations(computationDependencies, (PolymorphicInfo)referenced, existingConcepts, conceptInfo); } string referencePathWithGuid = ChangeReferenceToGuid(conceptInfo.ReferencePath); return(computationDependencies.Select(dep => new ChangesOnChangedItemsInfo { Computation = conceptInfo.Computation, DependsOn = dep.Item1, FilterType = "FilterCriteria", FilterFormula = $@"changedItems => new FilterCriteria({CsUtility.QuotedString(referencePathWithGuid)}, ""In""," + $" _domRepository.Common.FilterId.CreateQueryableFilterIds(changedItems.Select({dep.Item2})))" })); }
/// <summary> /// Clears the roles' authorization data from the cache: RoleRoles, RolePermissions and Role (full list). /// </summary> public void ClearCacheRoles(IEnumerable <Guid> roleIds) { CsUtility.Materialize(ref roleIds); _logger.Trace(() => "ClearCacheRoles: " + string.Join(", ", roleIds) + "."); var deleteKeys = roleIds.Distinct() .Select(roleId => "AuthorizationDataCache.RoleRoles." + roleId.ToString()) .Concat(roleIds.Select(roleId => "AuthorizationDataCache.RolePermissions." + roleId.ToString())) .Concat(new[] { "AuthorizationDataCache.Roles" }); var cache = MemoryCache.Default; foreach (string key in deleteKeys) { cache.Remove(key); } var systemRoles = (IDictionary <SystemRole, Guid>)cache.Get("AuthorizationDataCache.SystemRoles"); if (systemRoles != null && systemRoles.Values.Intersect(roleIds).Any()) { _logger.Trace(() => "ClearCacheRoles: SystemRoles."); cache.Remove("AuthorizationDataCache.SystemRoles"); } }
public static void Save(IEnumerable <InstalledPackage> packages) { CsUtility.Materialize(ref packages); string serialized = JsonConvert.SerializeObject(packages, _serializerSettings); File.WriteAllText(GetPackagesFilePath(), serialized, Encoding.UTF8); }
/// <summary> /// The function may return permissions for more claims than required. /// </summary> public IEnumerable <PrincipalPermissionInfo> GetPrincipalPermissions(IPrincipal principal, IEnumerable <Guid> claimIds = null) { CsUtility.Materialize(ref claimIds); if (claimIds != null && !claimIds.Any()) { return(Enumerable.Empty <PrincipalPermissionInfo>()); } var query = _principalPermissionRepository.Query() .Where(principalPermission => principalPermission.IsAuthorized != null && principalPermission.PrincipalID == principal.ID); if (claimIds != null && claimIds.Count() < _sqlFilterItemsLimit) { query = query.Where(principalPermission => claimIds.Contains(principalPermission.ClaimID.Value)); } return(query.Select(principalPermission => new PrincipalPermissionInfo { ID = principalPermission.ID, PrincipalID = principalPermission.PrincipalID.Value, ClaimID = principalPermission.ClaimID.Value, IsAuthorized = principalPermission.IsAuthorized.Value, }) .ToList()); }
/// <summary> /// The function may return permissions for more claims than required. /// </summary> public IEnumerable <RolePermissionInfo> GetRolePermissions(IEnumerable <Guid> roleIds, IEnumerable <Guid> claimIds = null) { CsUtility.Materialize(ref roleIds); CsUtility.Materialize(ref claimIds); if (!roleIds.Any() || (claimIds != null && !claimIds.Any())) { return(Enumerable.Empty <RolePermissionInfo>()); } var query = _rolePermissionRepository.Query() .Where(rolePermission => rolePermission.IsAuthorized != null && roleIds.Contains(rolePermission.RoleID.Value)); if (claimIds != null && claimIds.Count() < _sqlFilterItemsLimit) { query = query.Where(rolePermission => claimIds.Contains(rolePermission.ClaimID.Value)); } return(query.Select(rolePermission => new RolePermissionInfo { ID = rolePermission.ID, RoleID = rolePermission.RoleID.Value, ClaimID = rolePermission.ClaimID.Value, IsAuthorized = rolePermission.IsAuthorized.Value, }) .ToList()); }
public IEnumerable <TPlugin> GetImplementations(Type implements) { var typeHierarchy = CsUtility.GetClassHierarchy(implements); var allImplementations = typeHierarchy.SelectMany(type => PreSort(_pluginsByImplementation.Value[type])); return(_cache.SortedByMetadataDependsOnAndRemoveSuppressed(implements, allImplementations)); }
public IEnumerable <IConceptInfo> CreateNewConcepts(IEnumerable <IConceptInfo> existingConcepts) { var itemFilter = new ItemFilterInfo { Expression = String.Format("item => item.{0} != null && item.{1} != null && item.{0} > item.{1}", PropertyFrom.Name, PropertyTo.Name), FilterName = PropertyFrom.Name + "_" + PropertyTo.Name + "_RangeFilter", Source = PropertyFrom.DataStructure }; var invalidData = new InvalidDataInfo { Source = PropertyFrom.DataStructure, FilterType = itemFilter.FilterName, ErrorMessage = "Value of {0} has to be less than or equal to {1}." }; var messageParameters = new InvalidDataMessageParametersConstantInfo { InvalidData = invalidData, MessageParameters = CsUtility.QuotedString(PropertyFrom.Name) + ", " + CsUtility.QuotedString(PropertyTo.Name) }; var invalidProperty = new InvalidDataMarkProperty2Info { InvalidData = invalidData, MarkProperty = PropertyFrom }; return(new IConceptInfo[] { itemFilter, invalidData, messageParameters, invalidProperty }); }
private static string CheckLockedPropertySnippet(LockPropertyInfo info) { string propertyName = info.Source.Name; if (info.Source is ReferencePropertyInfo) { propertyName += "ID"; } return(string.Format( @"if (updatedNew.Count() > 0 || deletedIds.Count() > 0) {{ {0}[] changedItems = updated.Zip(updatedNew, (i, j) => ({4}) ? i : null).Where(x => x != null).ToArray(); if (changedItems != null && changedItems.Length > 0) {{ var lockedItems = _domRepository.{0}.Filter(this.Query(changedItems.Select(item => item.ID)), new {1}()); if (lockedItems.Count() > 0) throw new Rhetos.UserException({2}, ""DataStructure:{0},ID:"" + lockedItems.First().ID.ToString() + "",Property:{3}""); }} }} ", info.Source.DataStructure.GetKeyProperties(), info.FilterType, CsUtility.QuotedString(info.Title), propertyName, CompareValuePropertySnippet(propertyName))); }
public void GenerateCode(IConceptInfo conceptInfo, ICodeBuilder codeBuilder) { var info = (RegisteredInterfaceImplementationInfo)conceptInfo; var interfaceType = Type.GetType(info.InterfaceAssemblyQualifiedName); if (interfaceType == null) { throw new DslSyntaxException(conceptInfo, "Could not find type '" + info.InterfaceAssemblyQualifiedName + "'."); } // TODO: Remove IQueryableRepository registration. IQueryableRepository should be cast from repository object in Rhetos.Dom.DefaultConcepts.GenericRepositories class. string registerRepository = string.Format( @"builder.RegisterType<{0}._Helper.{1}_Repository>().As<IQueryableRepository<{2}>>().InstancePerLifetimeScope(); ", info.DataStructure.Module.Name, info.DataStructure.Name, interfaceType.FullName); codeBuilder.InsertCode(registerRepository, ModuleCodeGenerator.CommonAutofacConfigurationMembersTag); string registerImplementationName = string.Format( @"{{ typeof({0}), {1} }}, ", interfaceType.FullName, CsUtility.QuotedString( info.DataStructure.Module.Name + "." + info.DataStructure.Name)); codeBuilder.InsertCode(registerImplementationName, ModuleCodeGenerator.RegisteredInterfaceImplementationNameTag); }
private static IEnumerable <IConceptInfo> InitializeNonparsablePropertiesRecursive(IAlternativeInitializationConcept alternativeInitializationConcept, HashSet <string> alreadyCreated, int depth, ILogger traceLogger) { if (depth > 10) { throw new DslSyntaxException(alternativeInitializationConcept, "Macro concept references cannot be resolved."); } List <IConceptInfo> result = new List <IConceptInfo>(); IEnumerable <IConceptInfo> createdConcepts; alternativeInitializationConcept.InitializeNonparsableProperties(out createdConcepts); CsUtility.Materialize(ref createdConcepts); if (createdConcepts != null && createdConcepts.Count() > 0) { traceLogger.Trace(() => alternativeInitializationConcept.GetShortDescription() + " generated on alternative initialization: " + string.Join(", ", createdConcepts.Select(c => c.GetShortDescription())) + "."); result.AddRange(createdConcepts); foreach (var concept in createdConcepts.OfType <IAlternativeInitializationConcept>()) { if (!alreadyCreated.Contains(concept.GetFullDescription())) { alreadyCreated.Add(concept.GetFullDescription()); result.AddRange(InitializeNonparsablePropertiesRecursive(concept, alreadyCreated, depth + 1, traceLogger)); } } } return(result); }
public IEnumerable <IConceptInfo> CreateNewConcepts(IEnumerable <IConceptInfo> existingConcepts) { string filterName = "SystemRequired" + Property.Name; var filter = new ItemFilterInfo { Source = Property.DataStructure, FilterName = filterName, Expression = "item => item." + Property.Name + " == null" }; var invalidData = new InvalidDataInfo { Source = Property.DataStructure, FilterType = filterName, ErrorMessage = "System required property {0} is not set." }; var messageParameters = new InvalidDataMessageParametersConstantInfo { InvalidData = invalidData, MessageParameters = CsUtility.QuotedString(Property.GetUserDescription()) }; var invalidProperty = new InvalidDataMarkProperty2Info { InvalidData = invalidData, MarkProperty = Property }; return(new IConceptInfo[] { filter, invalidData, messageParameters, invalidProperty }); }
public IEnumerable <IConceptInfo> CreateNewConcepts(IEnumerable <IConceptInfo> existingConcepts) { var itemFilter = new ItemFilterInfo { Expression = String.Format("item => !String.IsNullOrEmpty(item.{0}) && item.{0}.Length > {1}", Property.Name, Length), FilterName = Property.Name + "_MaxLengthFilter", Source = Property.DataStructure }; var invalidData = new InvalidDataInfo { Source = Property.DataStructure, FilterType = itemFilter.FilterName, ErrorMessage = "Maximum allowed length of {0} is {1} characters." }; var messageParameters = new InvalidDataMessageParametersConstantInfo { InvalidData = invalidData, MessageParameters = CsUtility.QuotedString(Property.Name) + ", " + Length }; var invalidProperty = new InvalidDataMarkProperty2Info { InvalidData = invalidData, MarkProperty = Property }; return(new IConceptInfo[] { itemFilter, invalidData, messageParameters, invalidProperty }); }
public IEnumerable <IConceptInfo> CreateNewConcepts(IEnumerable <IConceptInfo> existingConcepts) { var filterParameter = new ParameterInfo { Module = Property.DataStructure.Module, Name = Property.Name + "_RegExMatchFilter", }; string filterExpression = string.Format(@"(source, repository, parameter) => {{ var items = source.Where(item => !string.IsNullOrEmpty(item.{0})).Select(item => new {{ item.ID, item.{0} }}).ToList(); var regex = new System.Text.RegularExpressions.Regex({1}); var invalidItemIds = items.Where(item => !regex.IsMatch(item.{0})).Select(item => item.ID).ToList(); return Filter(source, invalidItemIds); }}", Property.Name, CsUtility.QuotedString("^" + RegularExpression + "$")); var itemFilterRegExMatchProperty = new ComposableFilterByInfo { Expression = filterExpression, Parameter = filterParameter.Module.Name + "." + filterParameter.Name, Source = Property.DataStructure }; var invalidDataRegExMatchProperty = new InvalidDataMarkPropertyInfo { DependedProperty = Property, FilterType = itemFilterRegExMatchProperty.Parameter, ErrorMessage = ErrorMessage, Source = Property.DataStructure }; return(new IConceptInfo[] { filterParameter, itemFilterRegExMatchProperty, invalidDataRegExMatchProperty }); }
/// <summary> /// Returns after-deploy scripts, ordered by natural sort of file paths inside each package. /// </summary> private List <Script> GetScripts(InstalledPackage package) { string afterDeployFolder = Path.GetFullPath(Path.Combine(package.Folder, "AfterDeploy")); if (!Directory.Exists(afterDeployFolder)) { return new List <Script> { } } ; var files = Directory.GetFiles(afterDeployFolder, "*.*", SearchOption.AllDirectories) .OrderBy(path => CsUtility.GetNaturalSortString(path).Replace(@"\", @" \")); const string expectedExtension = ".sql"; var badFile = files.FirstOrDefault(file => Path.GetExtension(file).ToLower() != expectedExtension); if (badFile != null) { throw new FrameworkException("After-deploy script '" + badFile + "' does not have the expected extension '" + expectedExtension + "'."); } return(files.Select(path => new Script { Package = package, Path = path, Name = GetSimpleName(path, afterDeployFolder) }) .ToList()); }
private void LogConcepts(StringBuilder report, string reportName, IEnumerable <IConceptInfo> concepts, bool first = false) { CsUtility.Materialize(ref concepts); if (concepts != null && concepts.Any()) { report.Append(first ? "" : "\r\n").Append(reportName).Append(": ").Append(string.Join(", ", concepts.Select(c => c.GetShortDescription())) + "."); } }
public void Indent() { Assert.AreEqual("", CsUtility.Indent("", 0)); Assert.AreEqual(" a", CsUtility.Indent("a", 1)); Assert.AreEqual(" a", CsUtility.Indent("a", 2)); Assert.AreEqual(" a\r\n b", CsUtility.Indent("a\r\nb", 2)); Assert.AreEqual(" a\r\n b", CsUtility.Indent("a\nb", 2)); }
public void GenerateCode(IConceptInfo conceptInfo, ICodeBuilder codeBuilder) { var info = (InvalidDataErrorMetadataInfo)conceptInfo; codeBuilder.InsertCode( $"metadata[{CsUtility.QuotedString(info.Key)}] = {CsUtility.QuotedString(info.Value)};\r\n ", InvalidDataCodeGenerator.ErrorMetadataTag, info.InvalidData); }
protected static string AddFilterSnippet(ApplyFilterOnClientReadInfo info) { return(string.Format( @"{{ {0}, {1} }}, ", CsUtility.QuotedString(info.DataStructure.GetKeyProperties()), CsUtility.QuotedString(info.FilterName))); }
private void LogConcepts(StringBuilder report, string reportName, IEnumerable <IConceptInfo> concepts) { CsUtility.Materialize(ref concepts); if (concepts != null && concepts.Count() > 0) { report.Append("\r\n " + reportName + ": " + string.Join(", ", concepts.Select(c => c.GetShortDescription())) + "."); } }
public void GenerateCode(IConceptInfo conceptInfo, ICodeBuilder codeBuilder) { var info = (RowPermissionsInheritExtensionWriteInfo)conceptInfo; codeBuilder.InsertCode( ", " + CsUtility.QuotedString(info.Extends.ExtensionPropertyName()), RowPermissionsInheritWriteCodeGenerator.ExtensionReferenceTag, info.InheritWrite); }
public void NaturalSortTest_NonNumeric() { var tests = new[] { "", " ", " ", "a", ".", "-" }; foreach (var test in tests) { Assert.AreEqual(test, CsUtility.GetNaturalSortString(test)); } }