Get/Set pairs

This commit is contained in:
Spirtix 2023-06-19 19:59:42 +02:00
parent da7c7e526f
commit 2a4edfffef
9 changed files with 236 additions and 2 deletions

View File

@ -3,7 +3,7 @@ import mitmproxy.http
def routable(path):
methods = ['GetRules', 'LoginParent', 'RegisterParent', 'GetSubscriptionInfo', 'GetUserInfoByApiToken', 'IsValidApiToken_V2', 'ValidateName', 'GetDefaultNameSuggestion', 'RegisterChild', 'GetProfileByUserId', 'LoginChild', 'GetUserProfileByUserID']
methods = ['GetRules', 'LoginParent', 'RegisterParent', 'GetSubscriptionInfo', 'GetUserInfoByApiToken', 'IsValidApiToken_V2', 'ValidateName', 'GetDefaultNameSuggestion', 'RegisterChild', 'GetProfileByUserId', 'LoginChild', 'GetUserProfileByUserID', 'GetKeyValuePair', 'SetKeyValuePair']
for method in methods:
if method in path:
return True

View File

@ -1,15 +1,19 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using sodoff.Attributes;
using sodoff.Model;
using sodoff.Schema;
using sodoff.Services;
using sodoff.Util;
namespace sodoff.Controllers.Common;
public class ContentController : Controller {
private readonly DBContext ctx;
public ContentController(DBContext ctx) {
private KeyValueService keyValueService;
public ContentController(DBContext ctx, KeyValueService keyValueService) {
this.ctx = ctx;
this.keyValueService = keyValueService;
}
[HttpPost]
@ -50,4 +54,72 @@ public class ContentController : Controller {
return Ok();
}
}
[HttpPost]
[Produces("application/xml")]
[Route("ContentWebService.asmx/GetKeyValuePair")]
public Schema.PairData? GetKeyValuePair([FromForm] string apiToken, [FromForm] int pairId) {
// Find session by apiToken
Session? session = ctx.Sessions.FirstOrDefault(s => s.ApiToken == apiToken);
if (session is null)
return null;
// Get the pair
Model.PairData? pair = keyValueService.GetPairData(session, pairId);
return keyValueService.ModelToSchema(pair);
}
[HttpPost]
[Produces("application/xml")]
[Route("ContentWebService.asmx/SetKeyValuePair")]
public IActionResult SetKeyValuePair([FromForm] string apiToken, [FromForm] int pairId, [FromForm] string contentXML) {
Schema.PairData schemaData = XmlUtil.DeserializeXml<Schema.PairData>(contentXML);
// Get the session
Session? session = ctx.Sessions.FirstOrDefault(s => s.ApiToken == apiToken);
if (session is null)
return Ok(false);
bool result = keyValueService.SetPairData(session, pairId, schemaData);
return Ok(result);
}
[HttpPost]
[Produces("application/xml")]
[Route("ContentWebService.asmx/GetKeyValuePairByUserID")]
public Schema.PairData? GetKeyValuePairByUserID([FromForm] string apiToken, [FromForm] int pairId, [FromForm] string userId) {
Session? session = ctx.Sessions.FirstOrDefault(s => s.ApiToken == apiToken);
if (session is null)
return null;
ctx.Entry(session).State = EntityState.Detached; // Don't update the entity
session.VikingId = null;
session.UserId = userId;
Model.PairData? pair = keyValueService.GetPairData(session, pairId);
return keyValueService.ModelToSchema(pair);
}
[HttpPost]
[Produces("application/xml")]
[Route("ContentWebService.asmx/SetKeyValuePairByUserID")]
public IActionResult SetKeyValuePairByUserID([FromForm] string apiToken, [FromForm] int pairId, [FromForm] string userId, [FromForm] string contentXML) {
Schema.PairData schemaData = XmlUtil.DeserializeXml<Schema.PairData>(contentXML);
// Get the session
Session? session = ctx.Sessions.FirstOrDefault(s => s.ApiToken == apiToken);
if (session is null || string.IsNullOrEmpty(userId))
return Ok(false);
ctx.Entry(session).State = EntityState.Detached; // Don't update the entity
session.VikingId = null;
session.UserId = userId;
bool result = keyValueService.SetPairData(session, pairId, schemaData);
return Ok(result);
}
}

View File

@ -5,6 +5,8 @@ public class DBContext : DbContext {
public DbSet<User> Users { get; set; } = null!;
public DbSet<Viking> Vikings { get; set; } = null!;
public DbSet<Session> Sessions { get; set; } = null!;
public DbSet<Pair> Pairs { get; set; } = null!;
public DbSet<PairData> PairData { get; set; } = null!;
public string DbPath { get; }
public DBContext() {
@ -29,5 +31,16 @@ public class DBContext : DbContext {
builder.Entity<Viking>().HasMany(u => u.Sessions)
.WithOne(e => e.Viking);
builder.Entity<PairData>()
.HasKey(e => e.Id);
builder.Entity<PairData>().HasMany(p => p.Pairs)
.WithOne(e => e.PairData);
builder.Entity<Pair>()
.HasOne(p => p.PairData)
.WithMany(pd => pd.Pairs)
.HasForeignKey(p => p.MasterId)
.HasPrincipalKey(e => e.Id);
}
}

18
src/Model/Pair.cs Normal file
View File

@ -0,0 +1,18 @@
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace sodoff.Model;
public class Pair {
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public string Key { get; set; }
public string Value { get; set; }
public int MasterId { get; set; }
public virtual PairData PairData { get; set; }
}

21
src/Model/PairData.cs Normal file
View File

@ -0,0 +1,21 @@
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace sodoff.Model;
[Index(nameof(UserId))]
[Index(nameof(VikingId))]
public class PairData {
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public int PairId { get; set; }
public string? UserId { get; set; }
public string? VikingId { get; set; }
public virtual ICollection<Pair> Pairs { get; set; }
}

View File

@ -1,5 +1,6 @@
using Microsoft.AspNetCore.Mvc.Formatters;
using sodoff.Model;
using sodoff.Services;
using System.Xml;
var builder = WebApplication.CreateBuilder(args);
@ -8,8 +9,10 @@ var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options => {
options.OutputFormatters.Add(new XmlSerializerOutputFormatter(new XmlWriterSettings() { OmitXmlDeclaration = false }));
options.OutputFormatters.RemoveType<HttpNoContentOutputFormatter>();
});
builder.Services.AddDbContext<DBContext>();
builder.Services.AddScoped<KeyValueService>();
var app = builder.Build();

16
src/Schema/Pair.cs Normal file
View File

@ -0,0 +1,16 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "Pair", Namespace = "")]
[Serializable]
public class Pair {
[XmlElement(ElementName = "PairKey")]
public string PairKey;
[XmlElement(ElementName = "PairValue")]
public string PairValue;
[XmlElement(ElementName = "UpdateDate")]
public DateTime UpdateDate;
}

12
src/Schema/PairData.cs Normal file
View File

@ -0,0 +1,12 @@
using System.Xml.Serialization;
namespace sodoff.Schema;
[XmlRoot(ElementName = "Pairs", Namespace = "", IsNullable = true)]
[Serializable]
public class PairData {
[XmlElement("Pair", IsNullable = true)]
public Pair[] Pairs { get; set; }
}

View File

@ -0,0 +1,79 @@
using sodoff.Model;
using sodoff.Schema;
namespace sodoff.Services;
public class KeyValueService {
private readonly DBContext ctx;
public KeyValueService(DBContext ctx) {
this.ctx = ctx;
}
public Model.PairData? GetPairData(Session session, int pairId) {
Model.PairData? pair = null;
if (session.VikingId != null)
pair = ctx.PairData.FirstOrDefault(e => e.PairId == pairId && e.VikingId == session.VikingId);
else if (session.UserId != null)
pair = ctx.PairData.FirstOrDefault(e => e.PairId == pairId && e.UserId == session.UserId);
return pair;
}
public bool SetPairData(Session session, int pairId, Schema.PairData schemaData) {
// Get the pair
Model.PairData? pair = GetPairData(session, pairId);
// Create the pair if it doesn't exist
bool exists = true;
if (pair is null) {
pair = new Model.PairData {
PairId = pairId,
UserId = session.UserId,
VikingId = session.VikingId,
Pairs = new List<Model.Pair>()
};
exists = false;
}
// Update or create the key-value pairs
foreach (var p in schemaData.Pairs) {
if (string.IsNullOrEmpty(p.PairValue))
return false; // NOTE: The real server doesn't update anything if one value is empty
var pairItem = pair.Pairs.FirstOrDefault(e => e.Key == p.PairKey);
if (pairItem != null)
pairItem.Value = p.PairValue;
else {
pairItem = new Model.Pair {
Key = p.PairKey,
Value = p.PairValue
};
pair.Pairs.Add(pairItem);
}
}
if (exists)
ctx.PairData.Update(pair);
else
ctx.PairData.Add(pair);
ctx.SaveChanges();
return true;
}
public Schema.PairData? ModelToSchema(Model.PairData? model) {
if (model is null) return null;
// Convert to schema class
List<Schema.Pair> pairs = new List<Schema.Pair>();
foreach (var p in model.Pairs) {
pairs.Add(new Schema.Pair {
PairKey = p.Key,
PairValue = p.Value
});
}
return new Schema.PairData { Pairs = pairs.ToArray() };
}
}