Skip to content

Commit

Permalink
SNOW-395226 - Add 'application' connection setting to set a specific …
Browse files Browse the repository at this point in the history
…application name (#366)

Setting for partners to specify their application name.
  • Loading branch information
SimbaGithub authored Aug 26, 2021
1 parent 54e62a7 commit d95cca0
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 1 deletion.
47 changes: 47 additions & 0 deletions Snowflake.Data.Tests/SFConnectionIT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,53 @@ public void TestBasicConnection()
}
}

[Test]
public void TestApplicationName()
{
string[] validApplicationNames = { "test1234", "test_1234", "test-1234", "test.1234"};
string[] invalidApplicationNames = { "1234test", "test$A", "test<script>" };

// Valid names
foreach (string appName in validApplicationNames)
{
using (IDbConnection conn = new SnowflakeDbConnection())
{
conn.ConnectionString = ConnectionString;
conn.ConnectionString += $"application={appName}";
conn.Open();
Assert.AreEqual(ConnectionState.Open, conn.State);

conn.Close();
Assert.AreEqual(ConnectionState.Closed, conn.State);
}
}

// Invalid names
foreach (string appName in invalidApplicationNames)
{
using (IDbConnection conn = new SnowflakeDbConnection())
{
conn.ConnectionString = ConnectionString;
conn.ConnectionString += $"application={appName}";
try
{
conn.Open();
logger.Debug("{appName}");
Assert.Fail();

}
catch (SnowflakeDbException e)
{
// Expected
logger.Debug("Failed opening connection ", e);
Assert.AreEqual("08006", e.SqlState); // Connection failure
}

Assert.AreEqual(ConnectionState.Closed, conn.State);
}
}
}

[Test]
public void TestIncorrectUserOrPasswordBasicConnection()
{
Expand Down
7 changes: 7 additions & 0 deletions Snowflake.Data/Client/SnowflakeDbException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ public SnowflakeDbException(SFError error, params object[] args)
this.VendorCode = error.GetAttribute<SFErrorAttr>().errorCode;
}

public SnowflakeDbException(string sqlState, SFError error, params object[] args)
{
this.ErrorMessage = string.Format(rm.GetString(error.ToString()), args);
this.VendorCode = error.GetAttribute<SFErrorAttr>().errorCode;
this.SqlState = sqlState;
}

public SnowflakeDbException(Exception innerException, SFError error, params object[] args)
: base(string.Format(rm.GetString(error.ToString()), args), innerException)
{
Expand Down
6 changes: 6 additions & 0 deletions Snowflake.Data/Core/Authenticator/IAuthenticator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ public BaseAuthenticator(SFSession session, string authName)
this.authName = authName;
// Update the value for insecureMode because it can be different for each session
ClientEnv.insecureMode = session.properties[SFSessionProperty.INSECUREMODE];
if (session.properties.TryGetValue(SFSessionProperty.APPLICATION, out var applicationName))
{
// If an application name has been specified in the connection setting, use it
// Otherwise, it will default to the running process name
ClientEnv.application = applicationName;
}
}

//// <see cref="IAuthenticator.AuthenticateAsync"/>
Expand Down
13 changes: 12 additions & 1 deletion Snowflake.Data/Core/ErrorMessages.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Snowflake.Data/Core/ErrorMessages.resx
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@
<data name="INVALID_CONNECTION_STRING" xml:space="preserve">
<value>Connection string is invalid: {0}</value>
</data>
<data name="INVALID_CONNECTION_PARAMETER_VALUE" xml:space="preserve">
<value>Invalid parameter value {0} for {1}</value>
</data>
<data name="INVALID_DATA_CONVERSION" xml:space="preserve">
<value>Failed to convert data {0} from type {1} to type {2}.</value>
</data>
Expand Down
3 changes: 3 additions & 0 deletions Snowflake.Data/Core/SFError.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ public enum SFError

[SFErrorAttr(errorCode = 270054)]
UNSUPPORTED_SNOWFLAKE_TYPE_FOR_PARAM,

[SFErrorAttr(errorCode = 270055)]
INVALID_CONNECTION_PARAMETER_VALUE,
}

class SFErrorAttr : Attribute
Expand Down
15 changes: 15 additions & 0 deletions Snowflake.Data/Core/SFSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@
using System.Threading;
using System.Threading.Tasks;
using System.Net.Http;
using System.Text.RegularExpressions;

namespace Snowflake.Data.Core
{
class SFSession
{
private static readonly SFLogger logger = SFLoggerFactory.GetLogger<SFSession>();

private static readonly Regex APPLICATION_REGEX = new Regex(@"^[A-Za-z]([A-Za-z0-9.\-_]){1,50}$");

private const string SF_AUTHORIZATION_BASIC = "Basic";

private const string SF_AUTHORIZATION_SNOWFLAKE_FMT = "Snowflake Token=\"{0}\"";
Expand Down Expand Up @@ -99,6 +102,18 @@ internal SFSession(String connectionString, SecureString password)
{
properties = SFSessionProperties.parseConnectionString(connectionString, password);

// If there is an "application" setting, verify that it matches the expect pattern
properties.TryGetValue(SFSessionProperty.APPLICATION, out string applicationNameSetting);
if (!String.IsNullOrEmpty(applicationNameSetting) && !APPLICATION_REGEX.IsMatch(applicationNameSetting))
{
throw new SnowflakeDbException(
SnowflakeDbException.CONNECTION_FAILURE_SSTATE,
SFError.INVALID_CONNECTION_PARAMETER_VALUE,
applicationNameSetting,
SFSessionProperty.APPLICATION.ToString()
);
}

ParameterMap = new Dictionary<SFSessionParameter, object>();
int recommendedMinTimeoutSec = BaseRestRequest.DEFAULT_REST_RETRY_SECONDS_TIMEOUT;
int timeoutInSec = recommendedMinTimeoutSec;
Expand Down
2 changes: 2 additions & 0 deletions Snowflake.Data/Core/SFSessionProperty.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ internal enum SFSessionProperty
PROXYPASSWORD,
[SFSessionPropertyAttr(required = false)]
NONPROXYHOSTS,
[SFSessionPropertyAttr(required = false)]
APPLICATION,

}

Expand Down

0 comments on commit d95cca0

Please sign in to comment.