diff --git a/ChangeLog.md b/ChangeLog.md index a60a265..d9b64a4 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -6,6 +6,22 @@ All notable changes to MIMWAL project will be documented in this file. The "Unre * Support for multi-valued attributes in `[//Effective]` lookup in AuthZ workflows. * Implement Approve Request Activity. +* Support for `[//Value]` lookups in Query definitions across rest of the activities. + +------------ + +### Version 2.18.0318.0 + +#### Added + +* [ConvertNumberToList][ConvertNumberToListFunction] function. +* [Multiply][MultiplyFunction] function. +* [Divide][DivideFunction] function. +* [Mod][ModFunction] function. + +#### Changed + +* [ConvertToString][ConvertToStringFunction] will return null if the input parameter is null instead of throwing an exception. ------------ @@ -171,3 +187,7 @@ All notable changes to MIMWAL project will be documented in this file. The "Unre [ExecuteSqlScalarFunction]: https://github.com/Microsoft/MIMWAL/wiki/ExecuteSqlScalar-Function [ValueByKeyFunction]: https://github.com/Microsoft/MIMWAL/wiki/ValueByKey-Function [DateTimeFromStringFunction]: https://github.com/Microsoft/MIMWAL/wiki/DateTimeFromString-Function +[ConvertNumberToListFunction]: https://github.com/Microsoft/MIMWAL/wiki/ConvertNumberToList-Function +[MultiplyFunction]: https://github.com/Microsoft/MIMWAL/wiki/Multiply-Function +[DivideFunction]: https://github.com/Microsoft/MIMWAL/wiki/Divide-Function +[ModFunction]: https://github.com/Microsoft/MIMWAL/wiki/Mod-Function diff --git a/src/VersionInfo.cs b/src/VersionInfo.cs index 0cde2e4..56aa0ea 100644 --- a/src/VersionInfo.cs +++ b/src/VersionInfo.cs @@ -22,7 +22,7 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary /// Build Number (MMDD) /// Revision (if any on the same day) /// - internal const string Version = "2.17.1012.0"; + internal const string Version = "2.18.0318.0"; /// /// File Version information for the assembly consists of the following four values: @@ -31,6 +31,6 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary /// Build Number (MMDD) /// Revision (if any on the same day) /// - internal const string FileVersion = "2.17.1012.0"; + internal const string FileVersion = "2.18.0318.0"; } } \ No newline at end of file diff --git a/src/WAL.sln b/src/WAL.sln index 8c492c6..5c3278d 100644 --- a/src/WAL.sln +++ b/src/WAL.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WorkflowActivityLibrary", "WorkflowActivityLibrary\WorkflowActivityLibrary.csproj", "{E2F7C594-3E4A-42DF-B293-7CB418DAB0DA}" EndProject @@ -11,6 +11,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scripts", "Scripts", "{9B89 ProjectSection(SolutionItems) = preProject Scripts\CaptureTrace.cmd = Scripts\CaptureTrace.cmd Scripts\CompileLanguagePack.cmd = Scripts\CompileLanguagePack.cmd + Scripts\EncryptConnectionString.ps1 = Scripts\EncryptConnectionString.ps1 Scripts\EncryptData.ps1 = Scripts\EncryptData.ps1 Scripts\Register.ps1 = Scripts\Register.ps1 Scripts\RunPSLoggingSample.ps1 = Scripts\RunPSLoggingSample.ps1 diff --git a/src/WorkflowActivityLibrary/Common/EventIdentifier.cs b/src/WorkflowActivityLibrary/Common/EventIdentifier.cs index 98c0aa3..8157560 100644 --- a/src/WorkflowActivityLibrary/Common/EventIdentifier.cs +++ b/src/WorkflowActivityLibrary/Common/EventIdentifier.cs @@ -1238,6 +1238,26 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common /// public const int ExpressionFunctionDateTimeFromString = 11682; + /// + /// The event identifier for ExpressionFunction ConvertNumberToList events + /// + public const int ExpressionFunctionConvertNumberToList = 11683; + + /// + /// The event identifier for ExpressionFunction Multiply events + /// + public const int ExpressionFunctionMultiply = 11684; + + /// + /// The event identifier for ExpressionFunction Divide events + /// + public const int ExpressionFunctionDivide = 11685; + + /// + /// The event identifier for ExpressionFunction Mod events + /// + public const int ExpressionFunctionMod = 11686; + /// /// The event identifier for LookupEvaluator Constructor events /// @@ -3058,6 +3078,61 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common /// public const int ExpressionFunctionDateTimeFromStringInvalidFunctionParametersError = 41682; + /// + /// The event identifier for ExpressionFunction ConvertNumberToList events + /// + public const int ExpressionFunctionConvertNumberToListInvalidFunctionParameterCountError = 41683; + + /// + /// The event identifier for ExpressionFunction ConvertNumberToList events + /// + public const int ExpressionFunctionConvertNumberToListInvalidFirstFunctionParameterTypeError = 41683; + + /// + /// The event identifier for ExpressionFunction Multiply events + /// + public const int ExpressionFunctionMultiplyInvalidFunctionParameterCountError = 41684; + + /// + /// The event identifier for ExpressionFunction Multiply events + /// + public const int ExpressionFunctionMultiplyInvalidFirstFunctionParameterTypeError = 41684; + + /// + /// The event identifier for ExpressionFunction Multiply events + /// + public const int ExpressionFunctionMultiplyInvalidSecondFunctionParameterTypeError = 41684; + + /// + /// The event identifier for ExpressionFunction Divide events + /// + public const int ExpressionFunctionDivideInvalidFunctionParameterCountError = 41685; + + /// + /// The event identifier for ExpressionFunction Divide events + /// + public const int ExpressionFunctionDivideInvalidFirstFunctionParameterTypeError = 41685; + + /// + /// The event identifier for ExpressionFunction Divide events + /// + public const int ExpressionFunctionDivideInvalidSecondFunctionParameterTypeError = 41685; + + /// + /// The event identifier for ExpressionFunction Mod events + /// + public const int ExpressionFunctionModInvalidFunctionParameterCountError = 41686; + + /// + /// The event identifier for ExpressionFunction Mod events + /// + public const int ExpressionFunctionModInvalidFirstFunctionParameterTypeError = 41686; + + /// + /// The event identifier for ExpressionFunction Mod events + /// + public const int ExpressionFunctionModInvalidSecondFunctionParameterTypeError = 41686; + /// /// The event identifier for LookupEvaluator Constructor events /// diff --git a/src/WorkflowActivityLibrary/Common/ExpressionFunction.cs b/src/WorkflowActivityLibrary/Common/ExpressionFunction.cs index 366fe6e..50a6d2f 100644 --- a/src/WorkflowActivityLibrary/Common/ExpressionFunction.cs +++ b/src/WorkflowActivityLibrary/Common/ExpressionFunction.cs @@ -134,6 +134,9 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common case "CONVERTFROMBASE64": return this.ConvertFromBase64(); + case "CONVERTNUMBERTOLIST": + return this.ConvertNumberToList(); + case "CONVERTSIDTOSTRING": return this.ConvertSidToString(); @@ -189,6 +192,9 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common case "DATETIMESUBTRACT": return this.DateTimeSubtract(); + case "DIVIDE": + return this.Divide(); + case "EQ": return this.Eq(); @@ -246,6 +252,12 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common case "MID": return this.Mid(); + case "MOD": + return this.Mod(); + + case "MULTIPLY": + return this.Multiply(); + case "NORMALIZESTRING": return this.NormalizeString(); @@ -694,6 +706,63 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common } } + /// + /// This function is used to divide the first integer value by the second integer value. + /// Function Syntax: Divide(first:integer, second:integer) + /// + /// The integer quotient of the division of the first integer value by the second integer value. + private long Divide() + { + Logger.Instance.WriteMethodEntry(EventIdentifier.ExpressionFunctionDivide, "Evaluation Mode: '{0}'.", this.mode); + + try + { + if (this.parameters.Count != 2) + { + throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionDivideInvalidFunctionParameterCountError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidFunctionParameterCountError, this.function, 2, this.parameters.Count)); + } + + Type parameterType = typeof(long); + object parameter = this.parameters[0]; + if (!this.VerifyType(parameter, parameterType)) + { + throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionDivideInvalidFirstFunctionParameterTypeError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidFirstFunctionParameterTypeError, this.function, parameterType.Name, parameter.GetType().Name)); + } + + parameter = this.parameters[1]; + if (!this.VerifyType(parameter, parameterType)) + { + throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionDivideInvalidSecondFunctionParameterTypeError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidSecondFunctionParameterTypeError, this.function, parameterType.Name, parameter.GetType().Name)); + } + + long result; + if (this.mode != EvaluationMode.Parse) + { + long first = Convert.ToInt64(this.parameters[0], CultureInfo.InvariantCulture); + long second = Convert.ToInt64(this.parameters[1], CultureInfo.InvariantCulture); + + if (second == 0) + { + throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionDivideInvalidSecondFunctionParameterTypeError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidFunctionParameterError2, this.function, 2)); + } + + result = first / second; + + Logger.Instance.WriteVerbose(EventIdentifier.ExpressionFunctionDivide, "Divide('{0}', '{1}') returned '{2}'.", this.parameters[0], this.parameters[1], result); + } + else + { + result = 0; + } + + return result; + } + finally + { + Logger.Instance.WriteMethodExit(EventIdentifier.ExpressionFunctionDivide, "Evaluation Mode: '{0}'.", this.mode); + } + } + /// /// This function is used to determine the equivalence between two objects or values, returns true if they are equal. /// Function Syntax: Eq(value:object, value:object, boolean:CompareCase) @@ -3037,6 +3106,115 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common } } + /// + /// This function is used to calculate the remainder after dividing the first integer with the second integer. + /// Function Syntax: Mod(first:integer, second:integer) + /// + /// The remainder after dividing the first integer with the second integer. + private long Mod() + { + Logger.Instance.WriteMethodEntry(EventIdentifier.ExpressionFunctionMod, "Evaluation Mode: '{0}'.", this.mode); + + try + { + if (this.parameters.Count != 2) + { + throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionModInvalidFunctionParameterCountError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidFunctionParameterCountError, this.function, 2, this.parameters.Count)); + } + + Type parameterType = typeof(long); + object parameter = this.parameters[0]; + if (!this.VerifyType(parameter, parameterType)) + { + throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionModInvalidFirstFunctionParameterTypeError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidFirstFunctionParameterTypeError, this.function, parameterType.Name, parameter.GetType().Name)); + } + + parameter = this.parameters[1]; + if (!this.VerifyType(parameter, parameterType)) + { + throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionModInvalidSecondFunctionParameterTypeError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidSecondFunctionParameterTypeError, this.function, parameterType.Name, parameter.GetType().Name)); + } + + long result; + if (this.mode != EvaluationMode.Parse) + { + long first = Convert.ToInt64(this.parameters[0], CultureInfo.InvariantCulture); + long second = Convert.ToInt64(this.parameters[1], CultureInfo.InvariantCulture); + + if (second == 0) + { + throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionModInvalidSecondFunctionParameterTypeError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidFunctionParameterError2, this.function, 2)); + } + + result = first % second; + + Logger.Instance.WriteVerbose(EventIdentifier.ExpressionFunctionMod, "Mod('{0}', '{1}') returned '{2}'.", this.parameters[0], this.parameters[1], result); + } + else + { + result = 0; + } + + return result; + } + finally + { + Logger.Instance.WriteMethodExit(EventIdentifier.ExpressionFunctionMod, "Evaluation Mode: '{0}'.", this.mode); + } + } + + /// + /// This function is used to multiply two integer values. + /// Function Syntax: Multiply(first:integer, second:integer) + /// + /// The result of the multiplication of the two integer values. + private long Multiply() + { + Logger.Instance.WriteMethodEntry(EventIdentifier.ExpressionFunctionMultiply, "Evaluation Mode: '{0}'.", this.mode); + + try + { + if (this.parameters.Count != 2) + { + throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionMultiplyInvalidFunctionParameterCountError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidFunctionParameterCountError, this.function, 2, this.parameters.Count)); + } + + Type parameterType = typeof(long); + object parameter = this.parameters[0]; + if (!this.VerifyType(parameter, parameterType)) + { + throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionMultiplyInvalidFirstFunctionParameterTypeError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidFirstFunctionParameterTypeError, this.function, parameterType.Name, parameter.GetType().Name)); + } + + parameter = this.parameters[1]; + if (!this.VerifyType(parameter, parameterType)) + { + throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionMultiplyInvalidSecondFunctionParameterTypeError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidSecondFunctionParameterTypeError, this.function, parameterType.Name, parameter.GetType().Name)); + } + + long result; + if (this.mode != EvaluationMode.Parse) + { + long first = Convert.ToInt64(this.parameters[0], CultureInfo.InvariantCulture); + long second = Convert.ToInt64(this.parameters[1], CultureInfo.InvariantCulture); + + result = first * second; + + Logger.Instance.WriteVerbose(EventIdentifier.ExpressionFunctionMultiply, "Multiply('{0}', '{1}') returned '{2}'.", this.parameters[0], this.parameters[1], result); + } + else + { + result = 0; + } + + return result; + } + finally + { + Logger.Instance.WriteMethodExit(EventIdentifier.ExpressionFunctionMultiply, "Evaluation Mode: '{0}'.", this.mode); + } + } + /// /// This function is used to normalize the first string, first by replacing the character substitutions specfied in the second string /// and then removing all diacritics using the .NET string normalization function. @@ -4372,6 +4550,55 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary.Common } } + /// + /// This function is used to convert a a number to a list of numbers which can be used to define an Iteration. + /// Function Syntax: ConvertNumberToList(count:integer) + /// + /// A list of numbers starting from 1 to the specified input number. + private List ConvertNumberToList() + { + Logger.Instance.WriteMethodEntry(EventIdentifier.ExpressionFunctionConvertNumberToList, "Evaluation Mode: '{0}'.", this.mode); + + try + { + if (this.parameters.Count != 1) + { + throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionConvertNumberToListInvalidFunctionParameterCountError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidFunctionParameterCountError, this.function, 1, this.parameters.Count)); + } + + Type parameterType = typeof(int); + object parameter = this.parameters[0]; + + if (!this.VerifyType(parameter, parameterType)) + { + throw Logger.Instance.ReportError(EventIdentifier.ExpressionFunctionConvertNumberToListInvalidFirstFunctionParameterTypeError, new InvalidFunctionFormatException(Messages.ExpressionFunction_InvalidFirstFunctionParameterTypeError, this.function, parameterType.Name, parameter.GetType().Name)); + } + + List result = null; + + if (this.mode != EvaluationMode.Parse) + { + int count = Convert.ToInt32(parameter, CultureInfo.InvariantCulture); + if (count > 0) + { + result = new List(count); + for (int i = 1; i <= count; ++i) + { + result.Add(i); + } + } + + Logger.Instance.WriteVerbose(EventIdentifier.ExpressionFunctionConvertNumberToList, "ConvertNumberToList('{0}') returned '{1}'.", this.parameters[0], result); + } + + return result; + } + finally + { + Logger.Instance.WriteMethodExit(EventIdentifier.ExpressionFunctionConvertNumberToList, "Evaluation Mode: '{0}'.", this.mode); + } + } + /// /// This function is used to convert a byte array containing a security identifier to a string. /// Function Syntax: ConvertSidToString(sid:binary) diff --git a/src/WorkflowActivityLibrary/Messages.Designer.cs b/src/WorkflowActivityLibrary/Messages.Designer.cs index 437abf8..d518866 100644 --- a/src/WorkflowActivityLibrary/Messages.Designer.cs +++ b/src/WorkflowActivityLibrary/Messages.Designer.cs @@ -358,7 +358,7 @@ namespace MicrosoftServices.IdentityManagement.WorkflowActivityLibrary { } /// - /// Looks up a localized string similar to The function '{0}' expects list at position {1} to be of length '{2}'. It has a length of '{3}'.. + /// Looks up a localized string similar to The function '{0}' expects parameter at position {1} to be non-zero.. /// internal static string ExpressionFunction_InvalidFunctionParameterError2 { get { diff --git a/src/WorkflowActivityLibrary/Messages.resx b/src/WorkflowActivityLibrary/Messages.resx index 4a98132..dad3368 100644 --- a/src/WorkflowActivityLibrary/Messages.resx +++ b/src/WorkflowActivityLibrary/Messages.resx @@ -370,7 +370,7 @@ The function '{0}' expects parameter at position {1} to be of type '{2}' or '{3}'. It was supplied a '{4}' parameter. - The function '{0}' expects list at position {1} to be of length '{2}'. It has a length of '{3}'. + The function '{0}' expects parameter at position {1} to be non-zero. The function '{0}' expects first parameter to be of type '{1}' or '{2}' or '{3}'. It was supplied a '{4}' parameter.