diff --git a/.github/workflows/dependabot.yml b/.github/workflows/dependabot.yml
new file mode 100644
index 0000000..6c0211b
--- /dev/null
+++ b/.github/workflows/dependabot.yml
@@ -0,0 +1,9 @@
+version: 2
+updates:
+ - package-ecosystem: "nuget"
+ directory: "/"
+ schedule:
+ interval: "daily"
+ time: "03:00"
+ timezone: "UTC"
+ open-pull-requests-limit: 5
diff --git a/.gitignore b/.gitignore
index 8a34f04..e898e06 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,7 @@
/Assets/Plugins/.signature.p7s
/Assets/UnityXapiPublisher/Runtime/.vscode
+reports
+reports.meta
+.clj-kondo
+.lsp
+.vscode
diff --git a/Assemblies/Microsoft.Bcl.AsyncInterfaces.dll b/Assemblies/Microsoft.Bcl.AsyncInterfaces.dll
index 39fd131..3a2d14a 100755
Binary files a/Assemblies/Microsoft.Bcl.AsyncInterfaces.dll and b/Assemblies/Microsoft.Bcl.AsyncInterfaces.dll differ
diff --git a/Assemblies/RestSharp.dll b/Assemblies/RestSharp.dll
index 2a83591..b0e421b 100755
Binary files a/Assemblies/RestSharp.dll and b/Assemblies/RestSharp.dll differ
diff --git a/Assemblies/System.IO.Pipelines.dll b/Assemblies/System.IO.Pipelines.dll
new file mode 100755
index 0000000..cfae953
Binary files /dev/null and b/Assemblies/System.IO.Pipelines.dll differ
diff --git a/Assemblies/System.IO.Pipelines.dll.meta b/Assemblies/System.IO.Pipelines.dll.meta
new file mode 100644
index 0000000..117be69
--- /dev/null
+++ b/Assemblies/System.IO.Pipelines.dll.meta
@@ -0,0 +1,33 @@
+fileFormatVersion: 2
+guid: f887835dab94a489a87e6d553e1f176b
+PluginImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ iconMap: {}
+ executionOrder: {}
+ defineConstraints: []
+ isPreloaded: 0
+ isOverridable: 0
+ isExplicitlyReferenced: 0
+ validateReferences: 1
+ platformData:
+ - first:
+ Any:
+ second:
+ enabled: 1
+ settings: {}
+ - first:
+ Editor: Editor
+ second:
+ enabled: 0
+ settings:
+ DefaultValueInitialized: true
+ - first:
+ Windows Store Apps: WindowsStoreApps
+ second:
+ enabled: 0
+ settings:
+ CPU: AnyCPU
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assemblies/System.Runtime.CompilerServices.Unsafe.dll b/Assemblies/System.Runtime.CompilerServices.Unsafe.dll
index 51974c7..6e91f06 100755
Binary files a/Assemblies/System.Runtime.CompilerServices.Unsafe.dll and b/Assemblies/System.Runtime.CompilerServices.Unsafe.dll differ
diff --git a/Assemblies/System.Text.Encodings.Web.dll b/Assemblies/System.Text.Encodings.Web.dll
index 29ef2ae..de502b7 100755
Binary files a/Assemblies/System.Text.Encodings.Web.dll and b/Assemblies/System.Text.Encodings.Web.dll differ
diff --git a/Assemblies/System.Text.Json.dll b/Assemblies/System.Text.Json.dll
index 410e98a..b85d61e 100755
Binary files a/Assemblies/System.Text.Json.dll and b/Assemblies/System.Text.Json.dll differ
diff --git a/NuGet.config b/NuGet.config
index cc798bc..7761ba8 100644
--- a/NuGet.config
+++ b/NuGet.config
@@ -2,7 +2,7 @@
-
+
@@ -10,6 +10,6 @@
-
+
diff --git a/Runtime/LRS/Domain/Publisher.cs b/Runtime/LRS/Domain/Publisher.cs
index 35b6a0b..092f884 100644
--- a/Runtime/LRS/Domain/Publisher.cs
+++ b/Runtime/LRS/Domain/Publisher.cs
@@ -32,7 +32,8 @@ public static void InvokeStatementSent(JsonObject statement)
OnStatementSent?.Invoke(statement);
}
- private JsonObject formAgent() {
+ private JsonObject formAgent()
+ {
bool hasEmail = PlayerPrefs.HasKey("LRSEmail");
bool hasAccount = PlayerPrefs.HasKey("LRSAccountId") && PlayerPrefs.HasKey("LRSHomepage");
if (hasEmail)
@@ -78,8 +79,14 @@ private JsonObject formAgent() {
private String gameId { get { return PlayerPrefs.GetString("LRSGameId"); } }
private String gameDisplay { get { return PlayerPrefs.GetString("LRSGameDisplay"); } }
- private bool hasCustomActivityEnv { get { return PlayerPrefs.HasKey("LRSActivityId") &&
- PlayerPrefs.HasKey("LRSActivityDefinition"); } }
+ private bool hasCustomActivityEnv
+ {
+ get
+ {
+ return PlayerPrefs.HasKey("LRSActivityId") &&
+ PlayerPrefs.HasKey("LRSActivityDefinition");
+ }
+ }
private String customActivityId { get { return PlayerPrefs.GetString("LRSActivityId"); } }
private String customActivityDefinition { get { return PlayerPrefs.GetString("LRSActivityDefinition"); } }
@@ -114,13 +121,13 @@ private async Task GetLocation()
}
// otherwise, we go ahead and populate the cache by calling the API
- return await Task.Run(async () =>
+ var request = new RestRequest($"json/{ip}");
+ location = await client.GetAsync(request);
+ if (location != null)
{
- location = await client.GetJsonAsync(string.Format("json/{0}", ip));
downloadCache.TryAdd("location", location);
-
- return location;
- });
+ }
+ return location;
}
private async Task FormBasicStatement(String verbId,
@@ -152,7 +159,8 @@ private async Task FormBasicStatement(String verbId,
};
// location
- if (enableUserLocation) {
+ if (enableUserLocation)
+ {
JsonObject loc = await this.locationTask;
contextExtension["http://ip-api.com/location"] = loc;
}
@@ -161,7 +169,8 @@ private async Task FormBasicStatement(String verbId,
String activityDefinition = gameDisplay;
// if there's a custom ActivityID in the env, set activityId to that one.
- if (hasCustomActivityEnv) {
+ if (hasCustomActivityEnv)
+ {
activityId = customActivityId;
activityDefinition = customActivityDefinition;
}
@@ -185,7 +194,7 @@ private async Task FormBasicStatement(String verbId,
["platform"] = gameId,
["extensions"] = contextExtension
},
- ["timestamp"] = DateTime.UtcNow.ToString("o",CultureInfo.InvariantCulture)
+ ["timestamp"] = DateTime.UtcNow.ToString("o", CultureInfo.InvariantCulture)
};
return statementFn(statement);
@@ -203,14 +212,14 @@ private async Task FormBasicStatement(String verbId,
String activityDescription,
Func statementFn)
{
- Func setObjektFn = (s) =>
+ Func setObjektFn = (s) =>
{
s["object"]["id"] = activityID;
s["object"]["definition"]["name"]["en-US"] = activityDescription;
return statementFn(s);
};
- JsonObject statement = await FormBasicStatement(verbId,
+ JsonObject statement = await FormBasicStatement(verbId,
verbDisplay,
user,
gameId,
@@ -240,7 +249,8 @@ private JsonObject FormActivity(String activityID,
};
}
- private void DebugStatements(string statement, RestResponse response) {
+ private void DebugStatements(string statement, RestResponse response)
+ {
Debug.Log(statement);
Debug.Log(response.Content);
Debug.Log(response.ResponseStatus);
@@ -280,7 +290,7 @@ public void SendCompletedStatement(String activityID,
public async void SendStatement(String verbId,
String verbDisplay)
{
- Func identity = (s) =>
+ Func identity = (s) =>
{
return s;
};
@@ -300,7 +310,7 @@ public async void SendStatement(String verbId,
public async void SendStatement(String verbId,
String verbDisplay,
- Func statementFn)
+ Func statementFn)
{
var statement = await FormBasicStatement(verbId,
verbDisplay,
@@ -321,7 +331,7 @@ public async void SendStatement(String verbId,
String activityID,
String activityDisplay)
{
- Func identity = (s) =>
+ Func identity = (s) =>
{
return s;
};
@@ -345,7 +355,7 @@ public async void SendStatement(String verbId,
String verbDisplay,
String activityID,
String activityDisplay,
- Func statementFn)
+ Func statementFn)
{
var statement = await FormBasicStatement(verbId,
verbDisplay,
@@ -370,7 +380,7 @@ async void SendCustomStatement(String verbId,
String gameDisplay,
String registrationIdentifier)
{
- Func identity = (s) =>
+ Func identity = (s) =>
{
return s;
};
diff --git a/Runtime/LRS/Sender.cs b/Runtime/LRS/Sender.cs
index ba77092..d75773f 100644
--- a/Runtime/LRS/Sender.cs
+++ b/Runtime/LRS/Sender.cs
@@ -4,28 +4,33 @@
using System.Threading.Tasks;
-namespace LRS {
- public class Sender {
+namespace LRS
+{
+ public class Sender
+ {
public Sender(String LRSUrl,
String LRSKey,
- String LRSSecret)
+ String LRSSecret)
{
this.LRSUrl = LRSUrl;
this.LRSKey = LRSKey;
this.LRSSecret = LRSSecret;
}
- private String LRSUrl {set;get;}
- private String LRSKey {set;get;}
- private String LRSSecret {set;get;}
+ private String LRSUrl { set; get; }
+ private String LRSKey { set; get; }
+ private String LRSSecret { set; get; }
- public async Task SendStatement(String statement) {
- var client = new RestClient(LRSUrl) {
- Authenticator = new HttpBasicAuthenticator(LRSKey,LRSSecret)
+ public async Task SendStatement(String statement)
+ {
+ var options = new RestClientOptions(LRSUrl)
+ {
+ Authenticator = new HttpBasicAuthenticator(LRSKey, LRSSecret)
};
+ var client = new RestClient(options);
var request = new RestRequest("/xapi/statements", Method.Post);
request.AddHeader("Accept", "application/json");
- request.AddStringBody(statement,DataFormat.Json);
+ request.AddStringBody(statement, DataFormat.Json);
request.AddHeader("X-Experience-API-Version", "1.0.1");
return await client.ExecutePostAsync(request);
}
diff --git a/Tests/LRS/Domain/PublisherTest.cs b/Tests/LRS/Domain/PublisherTest.cs
index 5a078f4..d96bb2f 100644
--- a/Tests/LRS/Domain/PublisherTest.cs
+++ b/Tests/LRS/Domain/PublisherTest.cs
@@ -39,7 +39,7 @@ public class PublisherTest
string LRSAccountId = "123456";
string LRSHomepage = "https://www.yetanalytics.com";
- string LRSUsernameDisplay = "John Doe";
+ string LRSUsernameDisplay = "John Doe";
string LRSGameId = "http://video.games/button-clicker";
string LRSGameDisplay = "Button Clicker";
string LRSActivityId = "http://video.games/button-clicker/level/1";
@@ -51,13 +51,13 @@ public class PublisherTest
public void SetUp()
{
// set Account and homepage for a more anonymous and contained identity:
- PlayerPrefs.SetString("LRSAccountId",LRSAccountId);
- PlayerPrefs.SetString("LRSHomepage",LRSHomepage);
+ PlayerPrefs.SetString("LRSAccountId", LRSAccountId);
+ PlayerPrefs.SetString("LRSHomepage", LRSHomepage);
// Or if you prefer, Email can be set the following way:
//PlayerPrefs.SetString("LRSEmail","user@example.com");
- PlayerPrefs.SetString("LRSUsernameDisplay",LRSUsernameDisplay);
+ PlayerPrefs.SetString("LRSUsernameDisplay", LRSUsernameDisplay);
// Game Identity Data
// This sets the Platform of the statement under context.platform
@@ -72,7 +72,7 @@ public void SetUp()
// Session Identity Data
- PlayerPrefs.SetString("LRSSessionIdentifier",LRSSessionIdentifier);
+ PlayerPrefs.SetString("LRSSessionIdentifier", LRSSessionIdentifier);
// Location Data
// Add this to the PlayerPrefs if you wish to get user location data
@@ -83,19 +83,22 @@ public void SetUp()
public void SendStartedStatementBehaves()
{
Hook hook = new Hook();
- Publisher publisher = new Publisher("http://example.com/LRSUrl","LRSKey","LRSSecret");
+ Publisher publisher = new Publisher("http://example.com/LRSUrl", "LRSKey", "LRSSecret");
publisher.SendStartedStatement();
JsonObject statement = hook.results.First();
- Assert.AreEqual(LRSHomepage, statement["actor"]["account"]["homePage"].ToString());
- Assert.AreEqual(LRSAccountId, statement["actor"]["account"]["name"].ToString());
+ Assert.AreEqual(statement["actor"]["account"]["homePage"].ToString(), LRSHomepage);
+ Assert.AreEqual(statement["actor"]["account"]["name"].ToString(), LRSAccountId);
Assert.AreEqual("http://adlnet.gov/expapi/verbs/initialized", statement["verb"]["id"].ToString());
- Assert.AreEqual(LRSActivityId, statement["object"]["id"].ToString());
- Assert.AreEqual("", statement["object"]["definition"]["extensions"]["https://docs.unity3d.com/ScriptReference/XR.XRSettings.html"]["loadedDeviceName"].ToString());
- Assert.AreEqual("false", statement["object"]["definition"]["extensions"]["https://docs.unity3d.com/ScriptReference/XR.XRDisplaySubsystem.html"]["running"].ToString());
- Assert.AreEqual(LRSSessionIdentifier, statement["context"]["registration"].ToString());
- Assert.AreEqual(LRSGameId, statement["context"]["platform"].ToString());
- Assert.AreEqual("LinuxEditor", statement["context"]["extensions"]["https://docs.unity3d.com/ScriptReference/Application-platform.html"]["platform"].ToString());
+ Assert.AreEqual(statement["object"]["id"].ToString(),
+ LRSActivityId);
+ Assert.AreEqual(statement["object"]["definition"]["extensions"]["https://docs.unity3d.com/ScriptReference/XR.XRSettings.html"]["loadedDeviceName"].ToString(),
+ "");
+ Assert.AreEqual(statement["object"]["definition"]["extensions"]["https://docs.unity3d.com/ScriptReference/XR.XRDisplaySubsystem.html"]["running"].ToString(),
+ "false");
+ Assert.AreEqual(statement["context"]["registration"].ToString(), LRSSessionIdentifier);
+ Assert.AreEqual(statement["context"]["platform"].ToString(), LRSGameId);
+ Assert.That(statement["context"]["extensions"]["https://docs.unity3d.com/ScriptReference/Application-platform.html"]["platform"].ToString(), Does.Match("^.+Editor$"));
Assert.IsInstanceOf(statement["timestamp"].ToString());
}
@@ -104,14 +107,14 @@ public void SendStatement_ModifiedVerbs()
{
string verbId = "http://video.games/verbs/quit";
string verbName = "Quit";
-
+
Hook hook = new Hook();
- Publisher publisher = new Publisher("http://example.com/LRSUrl","LRSKey","LRSSecret");
+ Publisher publisher = new Publisher("http://example.com/LRSUrl", "LRSKey", "LRSSecret");
publisher.SendStatement(verbId, verbName);
JsonObject statement = hook.results.First();
Assert.AreEqual(verbId, statement["verb"]["id"].ToString());
- Assert.AreEqual(verbName, statement["verb"]["display"]["en-US"].ToString());
+ Assert.AreEqual(verbName, statement["verb"]["display"]["en-US"].ToString());
}
[Test]
@@ -121,17 +124,17 @@ public void SendStatement_ModifiedVerbsWithAdditionalChanges()
string verbName = "Quit";
string publisherName = "ACME Games Corp.";
- Func modifyFn = (statement) =>
+ Func modifyFn = (statement) =>
{
// modify the statement
- statement["object"]["definition"]["extensions"]["https://video.games/publisher"] = new JsonObject{ ["name"] = publisherName };
+ statement["object"]["definition"]["extensions"]["https://video.games/publisher"] = new JsonObject { ["name"] = publisherName };
// make sure to return for the callback
return statement;
};
-
+
Hook hook = new Hook();
- Publisher publisher = new Publisher("http://example.com/LRSUrl","LRSKey","LRSSecret");
+ Publisher publisher = new Publisher("http://example.com/LRSUrl", "LRSKey", "LRSSecret");
publisher.SendStatement(verbId, verbName, modifyFn);
JsonObject statement = hook.results.First();
@@ -147,16 +150,16 @@ public void SendStatement_ModifiedVerbsActivities()
string verbName = "Quit";
string activityId = "http://video.games/pong";
string activityName = "Pong";
-
+
Hook hook = new Hook();
- Publisher publisher = new Publisher("http://example.com/LRSUrl","LRSKey","LRSSecret");
+ Publisher publisher = new Publisher("http://example.com/LRSUrl", "LRSKey", "LRSSecret");
publisher.SendStatement(verbId, verbName, activityId, activityName);
JsonObject statement = hook.results.First();
Assert.AreEqual(verbId, statement["verb"]["id"].ToString());
Assert.AreEqual(verbName, statement["verb"]["display"]["en-US"].ToString());
Assert.AreEqual(activityId, statement["object"]["id"].ToString());
- Assert.AreEqual(activityName, statement["object"]["definition"]["name"]["en-US"].ToString());
+ Assert.AreEqual(activityName, statement["object"]["definition"]["name"]["en-US"].ToString());
}
[Test]
@@ -168,24 +171,24 @@ public void SendStatement_ModifiedVerbsActivitiesWithAdditionalChanges()
string activityName = "Pong";
string publisherName = "ACME Games Corp.";
- Func modifyFn = (statement) =>
+ Func modifyFn = (statement) =>
{
// modify the statement
- statement["object"]["definition"]["extensions"]["https://video.games/publisher"] = new JsonObject{ ["name"] = publisherName };
+ statement["object"]["definition"]["extensions"]["https://video.games/publisher"] = new JsonObject { ["name"] = publisherName };
// make sure to return for the callback
return statement;
};
-
+
Hook hook = new Hook();
- Publisher publisher = new Publisher("http://example.com/LRSUrl","LRSKey","LRSSecret");
+ Publisher publisher = new Publisher("http://example.com/LRSUrl", "LRSKey", "LRSSecret");
publisher.SendStatement(verbId, verbName, activityId, activityName, modifyFn);
JsonObject statement = hook.results.First();
Assert.AreEqual(verbId, statement["verb"]["id"].ToString());
Assert.AreEqual(verbName, statement["verb"]["display"]["en-US"].ToString());
Assert.AreEqual(activityId, statement["object"]["id"].ToString());
- Assert.AreEqual(activityName, statement["object"]["definition"]["name"]["en-US"].ToString());
+ Assert.AreEqual(activityName, statement["object"]["definition"]["name"]["en-US"].ToString());
Assert.AreEqual(publisherName, statement["object"]["definition"]["extensions"]["https://video.games/publisher"]["name"].ToString());
}
}
\ No newline at end of file
diff --git a/Tests/Tests.asmdef b/Tests/Tests.asmdef
index 7cf673c..329c548 100644
--- a/Tests/Tests.asmdef
+++ b/Tests/Tests.asmdef
@@ -16,10 +16,11 @@
"nunit.framework.dll",
"System.Text.Json.dll"
],
- "autoReferenced": false,
+ "autoReferenced": true,
"defineConstraints": [
"UNITY_INCLUDE_TESTS"
],
"versionDefines": [],
- "noEngineReferences": false
+ "noEngineReferences": false,
+ "testAssemblies": true
}
\ No newline at end of file
diff --git a/nvd.sh b/nvd.sh
new file mode 100755
index 0000000..63abbcc
--- /dev/null
+++ b/nvd.sh
@@ -0,0 +1,8 @@
+docker run --rm \
+ -v "$PWD:/src" -v "$PWD/reports:/reports" \
+ owasp/dependency-check:latest \
+ --project "unity-xapi-publisher" \
+ --scan /src/packages.config \
+ --format SARIF \
+ --out /reports \
+ --nvdApiKey "$NVD_API_KEY"
\ No newline at end of file
diff --git a/nvd.sh.meta b/nvd.sh.meta
new file mode 100644
index 0000000..b91da8e
--- /dev/null
+++ b/nvd.sh.meta
@@ -0,0 +1,7 @@
+fileFormatVersion: 2
+guid: 0d0bf1d460ab44fe1b538c1c40f9d353
+DefaultImporter:
+ externalObjects: {}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/package.json b/package.json
index a02bf60..974a625 100644
--- a/package.json
+++ b/package.json
@@ -1,11 +1,11 @@
{
"name": "com.yetanalytics.unity-xapi-publisher",
- "version": "1.1.0",
+ "version": "1.1.1",
"displayName": "Unity Xapi Publisher",
"description": "This package gives you the tooling needed to send basic statements to an LRS",
"unity": "2021.3",
"unityRelease": "4f1",
- "keywords": [
+ "keywords": [
"XAPI",
"integration",
"data"
diff --git a/packages.config b/packages.config
index e275658..f2f65ff 100644
--- a/packages.config
+++ b/packages.config
@@ -1,8 +1,9 @@
-
-
-
-
-
+
+
+
+
+
+