Starting API

One of the leading API requests has been added in an early form. So I can go back and make this code better. This is to get something to go off.
This commit is contained in:
JacobTech 2023-05-13 16:44:21 -04:00
parent a27144d54a
commit 7a157fdc5d
9 changed files with 214 additions and 18 deletions

View File

@ -51,6 +51,11 @@ public static class EXT
return Base.ShowError(ErrorCode.ServerError, Error.Message); return Base.ShowError(ErrorCode.ServerError, Error.Message);
} }
public static IActionResult ResponseToResult<TResult>(this ControllerBase Base, TResult Result) where TResult : HTTPResponse
{
return Base.StatusCode(StatusCodes.Status200OK, Result);
}
public static IActionResult ShowError(this ControllerBase Base, ErrorCode code, string Error) public static IActionResult ShowError(this ControllerBase Base, ErrorCode code, string Error)
{ {

View File

@ -5,8 +5,8 @@ namespace LuskiServer.Classes.TableDef;
public static class Categories public static class Categories
{ {
public static TableColumn<long> ID { get; } = new("id", true); public static TableColumn<long> ID { get; } = new("id", true);
public static TableColumn<string> Name { get; } = new("name"); public static TableColumn<string> Name { get; } = new("name") { DefaultValue = "New Category"};
public static TableColumn<string> Description { get; } = new("description"); public static TableColumn<string> Description { get; } = new("description") { DefaultValue = "Default Description"};
public static TableColumn<long[]> InnerCategories { get; } = new("inner_categories") { DefaultValue = Array.Empty<long>() }; public static TableColumn<long[]> InnerCategories { get; } = new("inner_categories") { DefaultValue = Array.Empty<long>() };
public static TableColumn<long[]> Channels { get; } = new("channels") { DefaultValue = Array.Empty<long>() }; public static TableColumn<long[]> Channels { get; } = new("channels") { DefaultValue = Array.Empty<long>() };
public static TableColumn<long[]> RoleOverides { get; } = new("role_overides") { DefaultValue = Array.Empty<long>() }; public static TableColumn<long[]> RoleOverides { get; } = new("role_overides") { DefaultValue = Array.Empty<long>() };

View File

@ -1,3 +1,4 @@
using System.Text;
using JacobTechEncryption.Enums; using JacobTechEncryption.Enums;
using LuskiServer.Enums; using LuskiServer.Enums;
using ServerDatabase; using ServerDatabase;
@ -9,15 +10,20 @@ public static class Channels
public static TableColumn<long> ID { get; } = new("id", true); public static TableColumn<long> ID { get; } = new("id", true);
public static TableColumn<ChannelType> Type { get; } = new("type"); public static TableColumn<ChannelType> Type { get; } = new("type");
public static TableColumn<DateTime> Epoch { get; } = new("epoch"); public static TableColumn<DateTime> Epoch { get; } = new("epoch");
public static TableColumn<byte[]> Name { get; } = new("name"); public static TableColumn<byte[]> Name { get; } = new("name") { DefaultValue = Encoding.UTF8.GetBytes("New Channel") };
public static TableColumn<byte[]> Description { get; } = new("description"); public static TableColumn<byte[]> Description { get; } = new("description") { DefaultValue = Encoding.UTF8.GetBytes("New Channel") };
public static TableColumn<string> Key { get; } = new("key"); public static TableColumn<string> Key { get; } = new("key") { DefaultValue = string.Empty };
public static TableColumn<long[]> RoleOverides { get; } = new("role_overides"); public static TableColumn<long[]> RoleOverides { get; } = new("role_overides") { DefaultValue = Array.Empty<long>() };
public static TableColumn<long[]> UserOverides { get; } = new("member_overides"); public static TableColumn<long[]> UserOverides { get; } = new("member_overides") { DefaultValue = Array.Empty<long>() };
public static TableColumn<EncryptionType> TitleEncryptionType { get; } = new("title_encryption_type"); public static TableColumn<EncryptionType> TitleEncryptionType { get; } = new("title_encryption_type") { DefaultValue = EncryptionType.None };
public static TableColumn<EncryptionType> DescriptionEncryptionType { get; } = new("description_encryption_type"); public static TableColumn<EncryptionType> DescriptionEncryptionType { get; } = new("description_encryption_type") { DefaultValue = EncryptionType.None };
public static TableColumn<EncryptionType[]> AllowedEncryptionTypes { get; } = new("allowed_encryption_types"); public static TableColumn<EncryptionType[]> AllowedEncryptionTypes { get; } = new("allowed_encryption_types") { DefaultValue = new [] { EncryptionType.RSA } };
public static TableColumn<EncoderType> TitleEncoderType { get; } = new("title_encoder_type"); public static TableColumn<EncoderType> TitleEncoderType { get; } = new("title_encoder_type") { DefaultValue = EncoderType.UTF8 };
public static TableColumn<EncoderType> DescriptionEncoderType { get; } = new("description_encoder_type"); public static TableColumn<EncoderType> DescriptionEncoderType { get; } = new("description_encoder_type") { DefaultValue = EncoderType.UTF8 };
public static TableColumn<EncoderType[]> AllowedEncoderTypes { get; } = new("allowed_encoder_types"); public static TableColumn<EncoderType[]> AllowedEncoderTypes { get; } = new("allowed_encoder_types") { DefaultValue = new []
{
EncoderType.UTF8, EncoderType.UTF16,
EncoderType.UTF32, EncoderType.ASCII,
EncoderType.Latin1, EncoderType.BigEndianUnicode
} };
} }

View File

@ -8,8 +8,8 @@ public class Users
public static TableColumn<long> ID { get; } = new("id", true); public static TableColumn<long> ID { get; } = new("id", true);
public static TableColumn<string> DisplayName { get; } = new("displayname"); public static TableColumn<string> DisplayName { get; } = new("displayname");
public static TableColumn<long> SelectedChannel { get; } = new("selected_channel"); public static TableColumn<long> SelectedChannel { get; } = new("selected_channel");
public static TableColumn<Status> Status { get; } = new("status"); public static TableColumn<Status> Status { get; } = new("status") { DefaultValue = Enums.Status.Offline };
public static TableColumn<PictureType> PictureType { get; } = new("picture_type"); public static TableColumn<PictureType> PictureType { get; } = new("picture_type") {DefaultValue = Enums.PictureType.png };
public static TableColumn<byte[]> Picture { get; } = new("picture"); public static TableColumn<byte[]> Picture { get; } = new("picture");
public static TableColumn<long[]> Roles { get; } = new("roles"); public static TableColumn<long[]> Roles { get; } = new("roles");
public static TableColumn<byte[]> Username { get; } = new("username"); public static TableColumn<byte[]> Username { get; } = new("username");
@ -20,5 +20,5 @@ public class Users
public static TableColumn<string> WSSTCP { get; } = new("wsstcp"); public static TableColumn<string> WSSTCP { get; } = new("wsstcp");
public static TableColumn<string> Token { get; } = new("token"); public static TableColumn<string> Token { get; } = new("token");
public static TableColumn<string[]> OfflineData { get; } = new("offline_data"); public static TableColumn<string[]> OfflineData { get; } = new("offline_data");
public static TableColumn<string> OffileKey { get; } = new("offline_key"); public static TableColumn<string> OffileKey { get; } = new("offline_key") {DefaultValue = string.Empty};
} }

View File

@ -0,0 +1,21 @@
using System.Security.Cryptography;
using JacobTechEncryption;
namespace LuskiServer.Classes.WebTypes;
public class File
{
public string name { get; set; } = default!;
public string[] data { get; set; } = default!;
public ulong? size { get; set; } = default!;
public long? id { get; set; } = default!;
internal void decrypt(RSAParameters key, string outkey)
{
if (name != null) name = Convert.ToBase64String(Encryption.RSA.Encrypt(Encryption.RSA.Decrypt(Convert.FromBase64String(name), key), outkey));
//for (int i = 0; i < data.Count(); i++)
// {
// data[i] = Convert.ToBase64String(Encryption.Encrypt(Encryption.Decrypt(Convert.FromBase64String(data[i]), key), outkey));
//}
}
}

View File

@ -0,0 +1,6 @@
namespace LuskiServer.Classes.WebTypes;
public class SocketBulkMessage : HTTPResponse
{
public SocketMessage[] messages { get; set; } = default!;
}

View File

@ -0,0 +1,10 @@
namespace LuskiServer.Classes.WebTypes;
public class SocketMessage : HTTPResponse
{
public long channel_id { get; set; } = default!;
public long user_id { get; set; } = default!;
public long id { get; set; } = default!;
public string content { get; set; } = default!;
public File[] files { get; set; } = default!;
}

View File

@ -0,0 +1,148 @@
using Asp.Versioning;
using JacobTechEncryption;
using JacobTechEncryption.Enums;
using LuskiServer.Classes;
using LuskiServer.Classes.TableDef;
using LuskiServer.Classes.WebTypes;
using LuskiServer.Enums;
using Microsoft.AspNetCore.Mvc;
using ServerDatabase;
namespace LuskiServer.Controllers.v1;
[ApiVersion(1)]
[ApiController]
public class SocketBulkMessageController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
try
{
if (!this.CanTokenRequest(out long ID, out IActionResult? toc) && toc != null) return toc;
if (!Request.Headers.ContainsKey("id")) return this.ShowError(ErrorCode.MissingHeader, "You did not give an channel id for the channel you want to get a message from");
string channel_id = Request.Headers["id"].First();
long MessagesToDownload = 50;
long Max = 200;
if (long.TryParse(channel_id, out long Channel_Id) && !Tables.Channels.TryRead(Channels.ID, out _, Channels.ID.CreateParameter(Channel_Id))) return this.ShowError(ErrorCode.InvalidHeader, "The the channel id you have given the server is not a valed id");
//This needs to be added but using the new permission system.
//if (!Luski.HasAccessToChannel(ID, Channel_Id)) return this.ShowError(ErrorCode.Forbidden);
if (Request.Headers.ContainsKey("messages")) _ = long.TryParse(Request.Headers["messages"].First(), out MessagesToDownload);
if (MessagesToDownload > Max) MessagesToDownload = Max;
string? MostRecentID = null;
string sign = "<";
if (!Request.Headers.ContainsKey("mostrecentid") || !long.TryParse(MostRecentID = Request.Headers["mostrecentid"].First(), out long mrid) || !Tables.Messages.TryRead(Messages.ID, out _, Messages.ID.CreateParameter(mrid), Messages.ChannelID.CreateParameter(Channel_Id)))
{
try
{
bool HasMRID = Tables.Messages.TryRead(Messages.ID, new Order() { Assending = false, Type = Messages.TimeStamp.Name }, out long MRID, Messages.ChannelID.CreateParameter(Channel_Id));
Console.WriteLine(MRID);
if (HasMRID)
{
MostRecentID = MRID.ToString();
sign += "=";
}
}
catch
{
return this.ResponseToResult(
new SocketBulkMessage()
{
messages = Array.Empty<SocketMessage>()
});
}
}
SocketBulkMessage all = new();
///StartDatabse(MessagesToDownload, Channel_Id, MostRecentID, sign, out SocketMessage[]? mmm);
SocketMessage[]? mmm = null;
if (MostRecentID != null)
{
var con2 = Luski.Database.CreateConnection();
con2.Open();
var cmd2 = con2.CreateCommand();
Console.WriteLine($"SELECT context,author_id,message_id,files FROM messages WHERE ts {sign} '{new Luski.Snowflake(long.Parse(MostRecentID)).Timestamp}' AND channel_id = '{Channel_Id}' ORDER BY ts DESC LIMIT {MessagesToDownload};");
cmd2.CommandText = $"SELECT context,author_id,message_id,files FROM messages WHERE ts {sign} '{new Luski.Snowflake(long.Parse(MostRecentID)).Timestamp}' AND channel_id = '{Channel_Id}' ORDER BY ts DESC LIMIT {MessagesToDownload};";
var reader2 = cmd2.ExecuteReader();
//Loop(Messages, Channel_Id, out mmm, reader);
long current = 0;
var mmmm = new List<SocketMessage>();
while (reader2.Read())
{
current++;
if (current <= MessagesToDownload)
{
SocketMessage Current = new();
//ReadRow(Channel_Id, reader, ref mmm);
Current.channel_id = Channel_Id;
int i2 = 0;
while (i2 < reader2.FieldCount)
{
//ReadCollume(reader.GetValue(i), ref msg, reader.GetName(i));
string name = reader2.GetName(i2);
object val = reader2.GetValue(i2);
if (name == "context") Current.content = Convert.ToBase64String((byte[])val);
else if (name == "author_id") Current.user_id = long.Parse(val.ToString());
else if (name == "message_id") Current.id = long.Parse(val.ToString());
else if (name == "files")
{
if (val is not DBNull)
{
if ((long[]?)val is not null && ((long[])val).Length > 0)
{
List<Classes.WebTypes.File> list = new();
foreach (long b in (long[])val)
{
var con = Luski.Database.CreateConnection();
con.Open();
var cmd = con.CreateCommand();
cmd.CommandText = $"SELECT name,size FROM files WHERE id = '{b}';";
var reader = cmd.ExecuteReader();
int i3 = 0;
Classes.WebTypes.File file = new()
{
data = null!,
id = b
};
while (reader.Read())
{
while (i3 < reader.FieldCount)
{
//ReadFileCollume(reader.GetValue(i), ref file, reader.GetName(i));
string name2 = reader2.GetName(i3);
object val2 = reader2.GetValue(i3);
if (name2 == "name") file.name = Convert.ToBase64String((byte[])val2);
else if (name2 == "size") file.size = ulong.Parse(val2.ToString());
else;
i3++;
}
if (i3 >= reader.FieldCount) break;
}
list.Add(file);
con.Close();
}
Current.files = list.ToArray();
}
}
}
i2++;
}
if (mmm == null) break;
mmmm.Add(Current);
}
else break;
}
mmm = mmmm.ToArray();
con2.Close();
}
if (mmm is not null) all.messages = mmm;
else all.messages = Array.Empty<SocketMessage>();
return this.ResponseToResult(all);
}
catch (Exception ex)
{
return this.ShowError(ex);
}
}
}

View File

@ -19,10 +19,10 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="7.0.0" /> <PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="7.0.0" />
<PackageReference Include="JacobTechEncryption" Version="1.0.0" /> <PackageReference Include="JacobTechEncryption" Version="1.0.1" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.3" /> <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.3" />
<PackageReference Include="Microsoft.Extensions.PlatformAbstractions" Version="1.1.0" /> <PackageReference Include="Microsoft.Extensions.PlatformAbstractions" Version="1.1.0" />
<PackageReference Include="ServerDatabase" Version="2.5.4" /> <PackageReference Include="ServerDatabase" Version="2.5.8" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" /> <PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.5.0" />
</ItemGroup> </ItemGroup>