public CreateJoinRoom() { var response = new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.UnsupportedMethod }); this.Post[$"/api/{Channel}"] = _ => { var createJoinRoomArgs = Serializer.Deserialize <CreateJoinRoomArgs>(this.Request.Body); var createJoinRoomOutput = new CreateJoinRoomOutput(); var playerToken = PlayerToken.Decode(this.Request.Headers["playertoken"].FirstOrDefault()); switch (playerToken.State) { case PlayerTokenState.Invalid: return(new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.InternalError, Message = "The specified PlayerToken is invalid." })); case PlayerTokenState.Expired: return(new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.InternalError, Message = "The specified PlayerToken has expired." })); } createJoinRoomOutput.JoinKey = new JoinKey(playerToken.ConnectUserId, createJoinRoomArgs.ServerType, createJoinRoomArgs.RoomId).Encode(); createJoinRoomOutput.Endpoints = new[] { new ServerEndpoint() { Address = "127.0.0.1", Port = 8184 } }; return(new ChannelResponse().Get(createJoinRoomOutput, this.Request.Headers["playertoken"].First())); }; }
public LoadMyPlayerObject() { var response = new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.UnsupportedMethod }); this.Post[$"/api/{Channel}"] = _ => { var loadMyPlayerObjectOutput = new LoadMyPlayerObjectOutput() { PlayerObject = new DatabaseObject() }; // return an error if the specified PlayerToken is invalid var playerToken = PlayerToken.Decode(this.Request.Headers["playertoken"].FirstOrDefault()); switch (playerToken.State) { case PlayerTokenState.Invalid: return(new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.InternalError, Message = "The specified PlayerToken is invalid." })); case PlayerTokenState.Expired: return(new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.InternalError, Message = "The specified PlayerToken has expired." })); } var collection = DatabaseHost.Client.GetDatabase(playerToken.GameId).GetCollection <BsonDocument>("PlayerObjects"); var document = collection.Find(Builders <BsonDocument> .Filter.Eq("Key", playerToken.ConnectUserId)).FirstOrDefault(); if (document == null) { return(new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.BigDBObjectDoesNotExist })); } // retrieve the document version if available if (document.TryGetValue("_version", out var value)) { loadMyPlayerObjectOutput.PlayerObject.Version = value.AsString; } // remove any lingering artifacts before deserialization foreach (var element in document.Elements.ToArray()) { if (element.Name.StartsWith("_")) { document.RemoveElement(element); } } var _databaseObject = JsonConvert.DeserializeObject <SentDatabaseObject>(document.ToJson()); loadMyPlayerObjectOutput.PlayerObject.Table = _databaseObject.Table; loadMyPlayerObjectOutput.PlayerObject.Key = _databaseObject.Key; loadMyPlayerObjectOutput.PlayerObject.Properties = _databaseObject.Properties; return(new ChannelResponse().Get(loadMyPlayerObjectOutput, this.Request.Headers["playertoken"].First())); }; }
public CreateObjects() { var response = new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.UnsupportedMethod }); this.Post[$"/api/{Channel}"] = _ => { var createObjectsArgs = Serializer.Deserialize <CreateObjectsArgs>(this.Request.Body); var createObjectsOutput = new CreateObjectsOutput(); var playerToken = PlayerToken.Decode(this.Request.Headers["playertoken"].FirstOrDefault()); switch (playerToken.State) { case PlayerTokenState.Invalid: return(new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.InternalError, Message = "The specified PlayerToken is invalid." })); case PlayerTokenState.Expired: return(new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.InternalError, Message = "The specified PlayerToken has expired." })); } // if they request no objects, return no objects if (createObjectsArgs.Objects.Length < 1) { createObjectsOutput.Objects = new DatabaseObject[0]; return(new ChannelResponse().Get(createObjectsOutput, this.Request.Headers["playertoken"].First())); } // To-Do: check for permissions to create objects var database = DatabaseHost.Client.GetDatabase(playerToken.GameId); var collection = database.GetCollection <BsonDocument>(createObjectsArgs.Objects[0].Table); var databaseObjects = new List <DatabaseObject>(); foreach (var databaseObject in createObjectsArgs.Objects.OrderByDescending(x => x.Table)) { // load collection once per unique table for performance reasons if (databaseObject.Table != collection.CollectionNamespace.CollectionName) { collection = database.GetCollection <BsonDocument>(databaseObject.Table); } // prevent creating objects in an internal table from the BigDB database if (!databaseObject.Table.All(char.IsLetterOrDigit)) { return(new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.AccessDenied, Message = "Table names cannot contain non-alphanumeric characters." })); } // prevent creating objects with invalid characters within the keys if (!databaseObject.Key.All(char.IsLetterOrDigit)) { return(new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.AccessDenied, Message = "DatabaseObject keys cannot contain non-alphanumeric characters." })); } // table names may only contain no more than 64 characters and no less than 1 character if (databaseObject.Table.Length < 1 || databaseObject.Table.Length > 64) { return(new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.AccessDenied, Message = "Table names must be between 1-64 characters in length." })); } // database object keys may only contain no more than 64 characters and no less than 1 character if (databaseObject.Key.Length < 1 || databaseObject.Key.Length > 64) { return(new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.AccessDenied, Message = "DatabaseObject keys must be between 1-64 characters in length." })); } // check if the collection exists in the respecctful database if (!database.ListCollections(new ListCollectionsOptions() { Filter = new BsonDocument("name", databaseObject.Table) }).Any()) { return(new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.UnknownTable })); } var document = collection.Find(Builders <BsonDocument> .Filter.Eq("Key", playerToken.ConnectUserId)).FirstOrDefault(); // load existing database objects if required if (createObjectsArgs.LoadExisting && document != null) { var existingDatabaseObject = new DatabaseObject(); if (document.TryGetValue("_version", out var value)) { existingDatabaseObject.Version = value.AsString; } // remove any lingering artifacts before deserialization foreach (var element in document.Elements.ToArray()) { if (element.Name.StartsWith("_")) { document.RemoveElement(element); } } var _existingDatabaseObject = JsonConvert.DeserializeObject <SentDatabaseObject>(document.ToJson()); existingDatabaseObject.Table = _existingDatabaseObject.Table; existingDatabaseObject.Key = _existingDatabaseObject.Key; existingDatabaseObject.Properties = _existingDatabaseObject.Properties; databaseObjects.Add(existingDatabaseObject); // skip inserting the existing database object into the database continue; } // insert the new database object into the database collection.InsertOne(BsonDocument.Parse(JsonConvert.SerializeObject(databaseObject)).Add("_version", "1")); // insert the database object into the the output databaseObjects.Add(new DatabaseObject() { Table = databaseObject.Table, Key = databaseObject.Key, Properties = databaseObject.Properties, Version = "1" }); } createObjectsOutput.Objects = databaseObjects.ToArray(); return(new ChannelResponse().Get(createObjectsOutput, this.Request.Headers["playertoken"].First(), false)); }; }
public LoadObjects() { var response = new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.UnsupportedMethod }); this.Post[$"/api/{Channel}"] = _ => { var playerToken = PlayerToken.Decode(this.Request.Headers["playertoken"].FirstOrDefault()); var loadObjectsArgs = Serializer.Deserialize <LoadObjectsArgs>(this.Request.Body); var loadObjectsOutput = new LoadObjectsOutput(); switch (playerToken.State) { case PlayerTokenState.Invalid: return(new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.InternalError, Message = "The specified PlayerToken is invalid." })); case PlayerTokenState.Expired: return(new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.InternalError, Message = "The specified PlayerToken has expired." })); } // prevent loading an internal table from the BigDB database if (!loadObjectsArgs.ObjectIds.Table.All(char.IsLetterOrDigit)) { return(new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.AccessDenied, Message = "Table names cannot contain non-alphanumeric characters." })); } // collection names may only contain no more than 64 characters and no less than 1 character if (loadObjectsArgs.ObjectIds.Table.Length < 1 || loadObjectsArgs.ObjectIds.Table.Length > 64) { return(new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.AccessDenied, Message = "Table names must be between 1-64 characters in length." })); } // retrieve the relevant database objects from the BigDB database var collection = DatabaseHost.Client.GetDatabase(playerToken.GameId).GetCollection <BsonDocument>(loadObjectsArgs.ObjectIds.Table); var databaseObjects = new List <DatabaseObject>(); foreach (var objectKey in loadObjectsArgs.ObjectIds.Keys) { // prevent creating objects with invalid characters within the keys if (!objectKey.All(char.IsLetterOrDigit)) { return(new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.AccessDenied, Message = "DatabaseObject keys cannot contain non-alphanumeric characters." })); } // database object keys may only contain no more than 64 characters and no less than 1 character if (objectKey.Length < 1 || objectKey.Length > 64) { return(new ChannelResponse().Get(new Error() { ErrorCode = (int)ErrorCode.AccessDenied, Message = "DatabaseObject keys must be between 1-64 characters in length." })); } // query the database for keys matching the key specified var document = collection.Find(Builders <BsonDocument> .Filter.Eq("Key", objectKey)).FirstOrDefault(); if (document != null) { var databaseObject = new DatabaseObject(); // retrieve the document version if available if (document.TryGetValue("_version", out var value)) { databaseObject.Version = value.AsString; } // remove any lingering artifacts before deserialization foreach (var element in document.Elements.ToArray()) { if (element.Name.StartsWith("_")) { document.RemoveElement(element); } } var _databaseObject = JsonConvert.DeserializeObject <SentDatabaseObject>(document.ToJson()); databaseObject.Table = _databaseObject.Table; databaseObject.Key = _databaseObject.Key; databaseObject.Properties = _databaseObject.Properties; databaseObjects.Add(databaseObject); } } loadObjectsOutput.Objects = databaseObjects.ToArray(); return(new ChannelResponse().Get(loadObjectsOutput, this.Request.Headers["playertoken"].First())); }; }