Documentation for the Unity C# Library
Loading...
Searching...
No Matches
PlatformAPIHandler.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using System.Net.Http;
4using System.Net.Http.Headers;
5using Newtonsoft.Json;
6using Newtonsoft.Json.Linq;
8using UnityEngine;
9
10namespace PixoVR.Apex
11{
30
31 public class APIHandler
32 {
33 public delegate void APIResponse(ResponseType type, HttpResponseMessage message, object responseData);
34 public APIResponse OnAPIResponse;
35
36 protected string URL = "";
37 protected HttpClient handlingClient = null;
38
39 // Move to a separate plugin
40 protected string webURL = "";
41 protected HttpClient webHandlingClient = null;
42
43 // Need to migrate to this in the future
44 protected string apiURL = "";
45 protected HttpClient apiHandlingClient = null;
46
47 public APIHandler()
48 : this(PlatformEndpoints.NorthAmerica_ProductionEnvironment) { }
49
50 public APIHandler(string endpointUrl)
51 {
52 handlingClient = new HttpClient();
53 SetEndpoint(endpointUrl);
54
55 webHandlingClient = new HttpClient();
56 apiHandlingClient = new HttpClient();
57 }
58
59 HttpResponseMessage HandleException(Exception exception)
60 {
61 Debug.LogWarning("Exception has occurred: " + exception.Message);
62 HttpResponseMessage badRequestResponse = new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest);
63 OnAPIResponse.Invoke(ResponseType.RT_FAILED_RESPONSE, badRequestResponse, null);
64 return badRequestResponse;
65 }
66
67 public void SetEndpoint(string endpointUrl)
68 {
69 EnsureURLHasProtocol(ref endpointUrl);
70
71 URL = endpointUrl;
72 Debug.Log("[APIHandler] Set Endpoint to " + URL);
73 handlingClient.BaseAddress = new Uri(URL);
74 }
75
76 public void SetWebEndpoint(string endpointUrl)
77 {
78 EnsureURLHasProtocol(ref endpointUrl);
79
80 webURL = endpointUrl;
81 webHandlingClient.BaseAddress = new Uri(webURL);
82 }
83
84 public void SetPlatformEndpoint(string endpointUrl)
85 {
86 EnsureURLHasProtocol(ref endpointUrl);
87
88 apiURL = endpointUrl;
89 apiHandlingClient.BaseAddress = new Uri(apiURL);
90 }
91
92 private void EnsureURLHasProtocol(ref string url)
93 {
94 if (!url.StartsWith("https://", StringComparison.InvariantCultureIgnoreCase))
95 {
96 if (url.StartsWith("http:", StringComparison.InvariantCultureIgnoreCase))
97 {
98#if UNITY_EDITOR
99 Debug.LogWarning("URL must be a secured http endpoint for production.");
100#else
101 Debug.LogError("URL must be a securated http endpoint.");
102#endif
103 }
104 else
105 {
106 url.Insert(0, "https://");
107 }
108 }
109 }
110
111 public async void Ping()
112 {
113 handlingClient.DefaultRequestHeaders.Clear();
114 handlingClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
115
116 HttpResponseMessage response;
117 try
118 {
119 response = await handlingClient.GetAsync("/ping");
120 }
121 catch (Exception ex)
122 {
123 response = HandleException(ex);
124 }
125
126 OnAPIResponse.Invoke(ResponseType.RT_PING, response, null);
127 }
128
129 public async void GenerateAssistedLogin(string authToken)
130 {
131 apiHandlingClient.DefaultRequestHeaders.Clear();
132 apiHandlingClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
133 apiHandlingClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
134
135 // Create the GraphQL request payload
136 var graphqlRequest = new
137 {
138 operationName = "generateAuthCode",
139 variables = new { input = new { } },
140 query = "mutation generateAuthCode($input: AuthCodeInput!) { generateAuthCode(input: $input) { code expiresAt __typename }}",
141 };
142
143 string jsonContent = JsonConvert.SerializeObject(graphqlRequest);
144 HttpContent requestContent = new StringContent(jsonContent, System.Text.Encoding.UTF8, "application/json");
145 HttpResponseMessage response;
146 object responseContent;
147 try
148 {
149 response = await apiHandlingClient.PostAsync("/v2/query", requestContent);
150 string body = await response.Content.ReadAsStringAsync();
151 Debug.Log(body);
152
153 // Parse the GraphQL response structure
154 JObject jsonResponse = JObject.Parse(body);
155
156 if (jsonResponse["data"] != null && jsonResponse["data"]["generateAuthCode"] != null)
157 {
158 // Extract the relevant data from the GraphQL response
159 string code = jsonResponse["data"]["generateAuthCode"]["code"]?.ToString();
160 string expiresAt = jsonResponse["data"]["generateAuthCode"]["expiresAt"]?.ToString();
161
162 // Create the GeneratedAssistedLogin object with the extracted data
164 {
165 AssistedLogin = new AssistedLoginCode { AuthCode = code, Expires = expiresAt },
166 };
167
168 responseContent = assistedLogin;
169 }
170 else if (jsonResponse["errors"] != null)
171 {
172 // Handle GraphQL errors
173 string errorMessage = jsonResponse["errors"]?[0]?["message"]?.ToString() ?? "Unknown GraphQL error";
174 responseContent = new FailureResponse { Error = "true", Message = errorMessage };
175 }
176 else
177 {
178 // Fallback error handling
179 responseContent = new FailureResponse
180 {
181 Error = "true",
182 Message = "Invalid response format from server",
183 };
184 }
185 }
186 catch (Exception ex)
187 {
188 Debug.LogError($"Error generating assisted login: {ex.Message}");
189 response = new HttpResponseMessage(System.Net.HttpStatusCode.InternalServerError);
190 responseContent = new FailureResponse { Error = "true", Message = ex.Message };
191 }
192
193 OnAPIResponse.Invoke(ResponseType.RT_GEN_AUTH_LOGIN, response, responseContent);
194 }
195
196 public async void LoginWithToken(string token)
197 {
198 Debug.Log($"[Platform API] Logging in with token: {token}");
199 apiHandlingClient.DefaultRequestHeaders.Clear();
200 apiHandlingClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
201 apiHandlingClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
202
203 Debug.Log($"[Platform API] Sending login with a token.");
204 HttpResponseMessage response = await apiHandlingClient.GetAsync("/v2/auth/validate-signature");
205 string body = await response.Content.ReadAsStringAsync();
206 Debug.Log($"[Platform API] Body returned as {body}");
207 object responseContent = JsonConvert.DeserializeObject<UserLoginResponseContent>(body);
208 if ((responseContent as UserLoginResponseContent).HasErrored())
209 {
210 responseContent = JsonConvert.DeserializeObject<FailureResponse>(body);
211 }
212
213 Debug.Log($"[Platform API] Got a valid login response!");
214 object loginResponseContent = (responseContent as UserLoginResponseContent).User;
215
216 OnAPIResponse.Invoke(ResponseType.RT_LOGIN, response, loginResponseContent);
217 }
218
219 public async void Login(LoginData login)
220 {
221 Debug.Log("[Platform API] Calling Login.");
222 handlingClient.DefaultRequestHeaders.Clear();
223
224 HttpContent loginRequestContent = new StringContent(JsonUtility.ToJson(login));
225 loginRequestContent.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/json");
226
227 Debug.Log("[Platform API] Call to post api login.");
228 HttpResponseMessage response = await handlingClient.PostAsync("/login", loginRequestContent);
229 string body = await response.Content.ReadAsStringAsync();
230 Debug.Log("[Platform API] Got response body: " + body);
231 object responseContent = JsonConvert.DeserializeObject<LoginResponseContent>(body);
232 if ((responseContent as LoginResponseContent).HasErrored())
233 {
234 responseContent = JsonConvert.DeserializeObject<FailureResponse>(body);
235 }
236
237 Debug.Log("[Platform API] Response content deserialized.");
238 OnAPIResponse.Invoke(ResponseType.RT_LOGIN, response, responseContent);
239 }
240
241 public async void GetUserData(string authToken, int userId)
242 {
243 handlingClient.DefaultRequestHeaders.Clear();
244 handlingClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
245 handlingClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
246
247 HttpResponseMessage response = await handlingClient.GetAsync(string.Format("/user/{0}", userId));
248 string body = await response.Content.ReadAsStringAsync();
249 object responseContent = JsonConvert.DeserializeObject<GetUserResponseContent>(body);
250 GetUserResponseContent userInfo = responseContent as GetUserResponseContent;
251 if ((responseContent as GetUserResponseContent).HasErrored())
252 {
253 responseContent = JsonConvert.DeserializeObject<FailureResponse>(body);
254 }
255
256 OnAPIResponse.Invoke(ResponseType.RT_GET_USER, response, responseContent);
257 }
258
259 public async void GetUserModules(string authToken, int userId)
260 {
261 handlingClient.DefaultRequestHeaders.Clear();
262 handlingClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
263 handlingClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
264
265 UserModulesRequestData usersModulesRequest = new UserModulesRequestData();
266 usersModulesRequest.UserIds.Add(userId);
267 HttpContent loginRequestContent = new StringContent(JsonUtility.ToJson(usersModulesRequest));
268 loginRequestContent.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/json");
269
270 HttpResponseMessage response = await handlingClient.PostAsync("/access/users", loginRequestContent);
271 string body = await response.Content.ReadAsStringAsync();
272 object responseContent = JsonConvert.DeserializeObject<GetUserModulesResponse>(body);
273 if ((responseContent as GetUserModulesResponse).HasErrored())
274 {
275 responseContent = JsonConvert.DeserializeObject<FailureResponse>(body);
276 }
277 else
278 {
279 (responseContent as GetUserModulesResponse).ParseData();
280 }
281
282 OnAPIResponse.Invoke(ResponseType.RT_GET_USER_MODULES, response, responseContent);
283 }
284
285 public async void GetQuickIDAuthenticationUsers(string serialNumber)
286 {
287 apiHandlingClient.DefaultRequestHeaders.Clear();
288 apiHandlingClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
289
290 HttpResponseMessage response = await apiHandlingClient.GetAsync(string.Format("/v2/auth/quick-id/get-users?serialNumber={0}", serialNumber));
291 string body = await response.Content.ReadAsStringAsync();
292
293 Debug.Log($"[Platform API] Body returned as {body}");
294
295 object responseContent = JsonConvert.DeserializeObject<QuickIDAuthGetUsersResponse>(body);
296 if ((responseContent as QuickIDAuthGetUsersResponse).HasErrored())
297 {
298 responseContent = JsonConvert.DeserializeObject<FailureResponse>(body);
299 }
300
301 OnAPIResponse.Invoke(ResponseType.RT_QUICK_ID_AUTH_GET_USERS, response, responseContent);
302 }
303
304 public async void QuickIDLogin(QuickIDLoginData login)
305 {
306 Debug.Log("[Platform API] Calling Quick ID login.");
307 apiHandlingClient.DefaultRequestHeaders.Clear();
308
309 HttpContent loginRequestContent = new StringContent(JsonUtility.ToJson(login));
310 Debug.Log("[Platform API] Quick ID login request content: " + JsonUtility.ToJson(login));
311 loginRequestContent.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/json");
312
313 Debug.Log("[Platform API] Call to post api Quick ID login.");
314 HttpResponseMessage response = await apiHandlingClient.PostAsync("/v2/auth/quick-id/login", loginRequestContent);
315 string body = await response.Content.ReadAsStringAsync();
316 Debug.Log("[Platform API] Got response body: " + body);
317 object responseContent = JsonConvert.DeserializeObject<PlatformLoginResponse>(body);
318
319 var loginResponseContent = new LoginResponseContent();
320 if ((responseContent as PlatformLoginResponse).HasErrored())
321 {
322 responseContent = JsonConvert.DeserializeObject<FailureResponse>(body);
323 }
324 else
325 {
326 var platformLoginResponse = responseContent as PlatformLoginResponse;
327
328 loginResponseContent.Token = platformLoginResponse.Token;
329 if (platformLoginResponse.User != null)
330 {
331 loginResponseContent.ID = platformLoginResponse.User.Id;
332 loginResponseContent.OrgId = platformLoginResponse.User.OrgId;
333 loginResponseContent.First = platformLoginResponse.User.FirstName;
334 loginResponseContent.Last = platformLoginResponse.User.LastName;
335 loginResponseContent.Email = platformLoginResponse.User.Email;
336 loginResponseContent.Role = platformLoginResponse.User.Role;
337 loginResponseContent.Org = platformLoginResponse.User.Org;
338 }
339 else
340 {
341 Debug.Log("[Platform API] Quick ID login response did not contain user data.");
342 }
343 }
344
345 Debug.Log("[Platform API] Response content deserialized and mapped.");
346 OnAPIResponse.Invoke(ResponseType.RT_QUICK_ID_AUTH_LOGIN, response, loginResponseContent);
347 }
348
349 public async void JoinSession(string authToken, JoinSessionData joinData)
350 {
351 handlingClient.DefaultRequestHeaders.Clear();
352 handlingClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
353 handlingClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
354
355 HttpContent joinSessionRequestContent = new StringContent(joinData.ToJSON());
356 joinSessionRequestContent.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/json");
357
358 HttpResponseMessage response = await handlingClient.PostAsync("/event", joinSessionRequestContent);
359 string body = await response.Content.ReadAsStringAsync();
360 object responseContent = JsonConvert.DeserializeObject<JoinSessionResponse>(body);
361 if ((responseContent as FailureResponse).HasErrored())
362 {
363 responseContent = null;
364 }
365 else
366 {
367 JoinSessionResponse joinSessionResponse = (responseContent as JoinSessionResponse);
368 joinSessionResponse.ParseData();
369 responseContent = joinSessionResponse;
370 }
371
372 OnAPIResponse.Invoke(ResponseType.RT_SESSION_JOINED, response, responseContent);
373 }
374
375 public async void GetModuleAccess(int moduleId, int userId, string serialNumber)
376 {
377 Debug.Log("[Platform API Handler] Get Module Access");
378 handlingClient.DefaultRequestHeaders.Clear();
379 handlingClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
380
381 string optionalParameters = "";
382 if (!string.IsNullOrEmpty(serialNumber))
383 {
384 optionalParameters = "?serial=" + serialNumber;
385 }
386
387 Debug.Log(
388 $"[{GetType().Name}] Checking module access at: "
389 + String.Format("/access/user/{0}/module/{1}{2}", userId, moduleId, optionalParameters)
390 );
391
392 HttpResponseMessage response = await handlingClient.GetAsync(
393 String.Format("/access/user/{0}/module/{1}{2}", userId, moduleId, optionalParameters)
394 );
395 string body = await response.Content.ReadAsStringAsync();
396
397 Debug.Log($"[{GetType().Name}] GetModuleAccess return body: {body}");
398 object responseContent = JsonConvert.DeserializeObject<FailureResponse>(body);
399 if (!(responseContent as FailureResponse).HasErrored())
400 {
401 responseContent = JsonConvert.DeserializeObject<UserAccessResponseContent>(body);
402 }
403 OnAPIResponse.Invoke(ResponseType.RT_GET_USER_ACCESS, response, responseContent);
404 }
405
406 public async void SendHeartbeat(string authToken, int sessionId)
407 {
408 apiHandlingClient.DefaultRequestHeaders.Clear();
409 apiHandlingClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
410 apiHandlingClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
411
412 HeartbeatData heartbeatData = new HeartbeatData(sessionId);
413
414 HttpContent heartbeatRequestContent = new StringContent(heartbeatData.ToJSON());
415 heartbeatRequestContent.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/json");
416
417 HttpResponseMessage response = await apiHandlingClient.PostAsync(
418 "/heartbeat/pulse",
419 heartbeatRequestContent
420 );
421 string body = await response.Content.ReadAsStringAsync();
422 object responseContent = JsonConvert.DeserializeObject<FailureResponse>(body);
423 if ((responseContent as FailureResponse).HasErrored())
424 {
425 responseContent = null;
426 }
427
428 OnAPIResponse.Invoke(ResponseType.RT_HEARTBEAT, response, responseContent);
429 }
430
431 public async void CompleteSession(string authToken, CompleteSessionData completionData)
432 {
433 handlingClient.DefaultRequestHeaders.Clear();
434 handlingClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
435 handlingClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
436
437 HttpContent completeSessionRequestContent = new StringContent(completionData.ToJSON());
438 completeSessionRequestContent.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/json");
439
440 HttpResponseMessage response = await handlingClient.PostAsync("/event", completeSessionRequestContent);
441 string body = await response.Content.ReadAsStringAsync();
442 object responseContent = JsonConvert.DeserializeObject<FailureResponse>(body);
443 if ((responseContent as FailureResponse).HasErrored())
444 {
445 responseContent = null;
446 }
447
448 OnAPIResponse.Invoke(ResponseType.RT_SESSION_COMPLETE, response, responseContent);
449 }
450
451 public async void SendSessionEvent(string authToken, SessionEventData sessionEvent)
452 {
453 handlingClient.DefaultRequestHeaders.Clear();
454 handlingClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
455 handlingClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
456
457 HttpContent sessionEventRequestContent = new StringContent(sessionEvent.ToJSON());
458 sessionEventRequestContent.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/json");
459
460 HttpResponseMessage response = await handlingClient.PostAsync("/event", sessionEventRequestContent);
461 string body = await response.Content.ReadAsStringAsync();
462 object responseContent = JsonConvert.DeserializeObject<FailureResponse>(body);
463 if ((responseContent as FailureResponse).HasErrored())
464 {
465 responseContent = null;
466 }
467
468 OnAPIResponse.Invoke(ResponseType.RT_SESSION_EVENT, response, responseContent);
469 }
470
471 public async void GetModuleList(string authToken, string platform)
472 {
473 handlingClient.DefaultRequestHeaders.Clear();
474 handlingClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
475 handlingClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
476
477 string endpoint = "/modules";
478 if (platform != null && platform.Length > 0)
479 {
480 endpoint += $"?platform={platform}";
481 }
482
483 Debug.Log($"GetModuleList built endpoint: {endpoint}");
484
485 HttpResponseMessage response = await handlingClient.GetAsync(endpoint);
486 string body = await response.Content.ReadAsStringAsync();
487
488 try
489 {
490 var responseContent = JsonConvert.DeserializeObject<FailureResponse>(body);
491 OnAPIResponse.Invoke(ResponseType.RT_GET_MODULES_LIST, response, responseContent);
492 return;
493 }
494 catch (Exception ex)
495 {
496 Debug.LogWarning(ex);
497 }
498
499 List<OrgModule> orgModules = new List<OrgModule>();
500 JArray array = JArray.Parse(body);
501 if (array != null)
502 {
503 var tokens = array.Children();
504 foreach (JToken selectedToken in tokens)
505 {
506 OrgModule orgModule = ScriptableObject.CreateInstance<OrgModule>();
507 orgModule.Parse(selectedToken);
508 orgModules.Add(orgModule);
509 }
510 }
511
512 Debug.Log(orgModules.Count.ToString());
513 OnAPIResponse.Invoke(ResponseType.RT_GET_MODULES_LIST, response, orgModules);
514 }
515 }
516}
async void SendHeartbeat(string authToken, int sessionId)
APIHandler(string endpointUrl)
async void GetUserModules(string authToken, int userId)
async void QuickIDLogin(QuickIDLoginData login)
HttpResponseMessage HandleException(Exception exception)
void EnsureURLHasProtocol(ref string url)
async void JoinSession(string authToken, JoinSessionData joinData)
async void LoginWithToken(string token)
async void CompleteSession(string authToken, CompleteSessionData completionData)
async void Login(LoginData login)
async void SendSessionEvent(string authToken, SessionEventData sessionEvent)
void SetPlatformEndpoint(string endpointUrl)
async void GetQuickIDAuthenticationUsers(string serialNumber)
async void GetUserData(string authToken, int userId)
delegate void APIResponse(ResponseType type, HttpResponseMessage message, object responseData)
void SetEndpoint(string endpointUrl)
void SetWebEndpoint(string endpointUrl)
async void GetModuleAccess(int moduleId, int userId, string serialNumber)
async void GenerateAssistedLogin(string authToken)
async void GetModuleList(string authToken, string platform)
[Serializable]
Definition ApexTypes.cs:163
void Parse(JToken token)
Definition ApexTypes.cs:393
[Serializable]
Definition ApexTypes.cs:608