2023-08-21 10:58:17 -04:00
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Security.Authentication ;
using System.Text ;
using System.Text.Json ;
using System.Threading ;
using System.Threading.Tasks ;
using JacobTechEncryption ;
using JacobTechEncryption.Enums ;
using Luski.net.Enums ;
using Luski.net.JsonTypes ;
using Luski.net.JsonTypes.WSS ;
using Luski.net.Structures.Public ;
2024-03-20 23:18:34 -04:00
using Luski.Shared.PublicServers.V1.ClientToServer.HTTP ;
using Luski.Shared.PublicServers.V1.Enums ;
using Luski.Shared.PublicServers.V1.ServerToClient.HTTP ;
2023-08-21 10:58:17 -04:00
using WebSocketSharp ;
2024-03-20 23:18:34 -04:00
using DataType = Luski . Shared . PublicServers . V1 . Enums . DataType ;
2023-08-21 10:58:17 -04:00
namespace Luski.net ;
public partial class PublicServer
{
public async Task < bool > Login ( string Username , string Password , CancellationToken CancellationToken )
{
2024-03-20 23:18:34 -04:00
return await All ( Username , CancellationToken , Password ) ;
2023-08-21 10:58:17 -04:00
}
2024-03-20 23:18:34 -04:00
public async Task < bool > CreateAccount ( string Username , string Password , string DisplayName , string PFP , CancellationToken CancellationToken )
2023-08-21 10:58:17 -04:00
{
2024-03-20 23:18:34 -04:00
return await All ( Username , CancellationToken , Password , DisplayName , PFP ) ;
2023-08-21 10:58:17 -04:00
}
internal async Task < bool > LoginViaToken ( string t )
{
2024-03-20 23:18:34 -04:00
Console . WriteLine ( "Starting Auto Login:" ) ;
bool b = await All ( t , CancellationToken . None ) ;
Console . WriteLine ( $"Auto Login {(b ? " Successful " : " Failed ")}" ) ;
return b ;
2023-08-21 10:58:17 -04:00
}
2024-03-20 23:18:34 -04:00
private async Task < bool > All ( string Username , CancellationToken CancellationToken , string? Password = null , string? Displayname = null , string? pfp = null )
2023-08-21 10:58:17 -04:00
{
2024-03-20 23:18:34 -04:00
DateTime dt = DateTime . UtcNow ;
Console . WriteLine ( "Encryption: " + DateTime . UtcNow . Subtract ( dt ) . ToString ( "g" ) ) ;
2023-08-21 10:58:17 -04:00
if ( ! EncryptionHandler . Generating )
{
EncryptionHandler . GenerateKeys ( ) ;
}
2024-08-27 10:57:22 -04:00
while ( ! EncryptionHandler . Generated ) { Thread . Sleep ( 200 ) ; }
2024-03-20 23:18:34 -04:00
Console . WriteLine ( "Encryption 2: " + DateTime . UtcNow . Subtract ( dt ) . ToString ( "g" ) ) ;
List < Tuple < string , string , Exception > > FailedSystems = new ( ) ;
2023-08-21 10:58:17 -04:00
login = true ;
2024-03-20 23:18:34 -04:00
LoginSTC json ;
2023-08-21 10:58:17 -04:00
List < KeyValuePair < string , string? > > heads = new ( )
{
new ( "key" , EncryptionHandler . MyPublicKey ) ,
2024-03-20 23:18:34 -04:00
new ( ( Password is null ? "token" : "username" ) , Convert . ToBase64String ( Encryption . RSA . Encrypt ( Username , EncryptionHandler . ServerPublicKey , EncoderType . UTF16 ) ) )
2023-08-21 10:58:17 -04:00
} ;
2024-03-20 23:18:34 -04:00
if ( Password is not null )
{
heads . Add ( new ( "password" , EncryptionHandler . RemotePasswordEncrypt ( Encryption . Generic . Encoders [ ( int ) EncoderType . UTF16 ] . GetBytes ( Password ) ) ) ) ;
}
2023-08-21 10:58:17 -04:00
if ( File . Exists ( "LastPassVer.txt" ) & & int . TryParse ( File . ReadAllText ( "LastPassVer.txt" ) , out int lpv ) & & lpv < EncryptionHandler . PasswordVersion & & lpv > = 0 )
{
heads . Add ( new ( "old_password" , EncryptionHandler . RemotePasswordEncrypt ( Encoding . Unicode . GetBytes ( Password ) , lpv ) ) ) ;
heads . Add ( new ( "old_version" , lpv . ToString ( ) ) ) ;
}
if ( pfp is not null )
{
heads . Add ( new ( "displayname" , Displayname ) ) ;
json = await SendServer (
"SocketAccount" ,
pfp ,
2024-03-20 23:18:34 -04:00
LoginSTCContext . Default . LoginSTC ,
2023-08-21 10:58:17 -04:00
CancellationToken ,
heads . ToArray ( ) ) ;
}
else
{
json = await GetFromServer (
2024-03-20 23:18:34 -04:00
( Password is null ? "SocketAccount/AccessToken" : "SocketAccount" ) ,
LoginSTCContext . Default . LoginSTC ,
2023-08-21 10:58:17 -04:00
CancellationToken ,
heads . ToArray ( ) ) ;
}
2024-03-20 23:18:34 -04:00
Console . WriteLine ( "Account Result: " + DateTime . UtcNow . Subtract ( dt ) . ToString ( "g" ) ) ;
if ( json . Error is not null )
{
2024-11-18 23:24:23 -05:00
ConnectionStatus = ConnectionStatus . FailedToLogin ;
2024-03-20 23:18:34 -04:00
Console . WriteLine ( json . ErrorMessage ) ;
return false ;
throw new Exception ( $"Luski appears to be down at the current moment: {json.ErrorMessage}" ) ;
}
2023-08-21 10:58:17 -04:00
if ( EncryptionHandler . OfflinePrivateKey is null | | EncryptionHandler . OfflinePublicKey is null ) throw new Exception ( "Something went wrong generating the offline keys" ) ;
login = false ;
if ( json is not null & & json . Error is null )
{
ServerOut = new WebSocket ( wssurl ) ;
ServerOut . SslConfiguration . EnabledSslProtocols = SslProtocols . Tls13 | SslProtocols . Tls12 ;
ServerOut . OnMessage + = DataFromServer ;
ServerOut . WaitTime = new TimeSpan ( 0 , 0 , 5 ) ;
ServerOut . EmitOnPing = true ;
ServerOut . OnError + = ServerOut_OnError ;
ServerOut . Connect ( ) ;
2024-03-20 23:18:34 -04:00
Console . WriteLine ( "WSS Connection: " + DateTime . UtcNow . Subtract ( dt ) . ToString ( "g" ) ) ;
2023-08-21 10:58:17 -04:00
SendServer ( DataType . Token , new WSSLogin ( ) { Token = json . Token ! } ) ;
while ( Token is null & & Error is null )
{
2024-03-20 23:18:34 -04:00
Thread . Sleep ( 200 ) ;
2023-08-21 10:58:17 -04:00
}
if ( Error is not null )
{
throw new Exception ( Error ) ;
}
2024-03-20 23:18:34 -04:00
Console . WriteLine ( "WSS Login: " + DateTime . UtcNow . Subtract ( dt ) . ToString ( "g" ) ) ;
2023-08-21 10:58:17 -04:00
if ( Token is null ) throw new Exception ( "Server did not send a token" ) ;
CanRequest = true ;
long id = long . Parse ( Encoding . UTF8 . GetString ( Convert . FromBase64String (
Token . Split ( '.' ) [ 0 ]
) ) ) ;
User = await GetUser < SocketAppUser > ( id , CancellationToken ) ;
2024-11-18 23:24:23 -05:00
ConnectionStatus = ConnectionStatus . LoggedIn ;
2024-03-20 23:18:34 -04:00
User . Username = Username ;
Console . WriteLine ( "Get our info: " + DateTime . UtcNow . Subtract ( dt ) . ToString ( "g" ) ) ;
#region Extra Systems
Task . Run ( async ( ) = > {
#region Data Storage
try
2023-08-21 10:58:17 -04:00
{
2024-03-20 23:18:34 -04:00
StorageInfoSTC data ;
if ( Storage . StorageID = = 0 )
{
EncryptionHandler . Hash = Storage . GenerateStorage ( ) ;
data = await SendServer ( "OfflineData/Info" ,
new StorageInfoCTS ( )
{
Password = Convert . ToBase64String ( Encryption . AES . Encrypt ( EncryptionHandler . Hash , Storage . GetResourceBytes ( StorageDirectory . StorageInfo , "lpk" ) ) )
} ,
StorageInfoCTSContext . Default . StorageInfoCTS ,
StorageInfoSTCContext . Default . StorageInfoSTC , CancellationToken ,
new KeyValuePair < string , string? > ( "storage_id" , Storage . StorageID . ToString ( ) ) ) ;
Storage . setid ( data . ID ) ;
}
else
{
data = await GetFromServer ( "OfflineData/Info" , StorageInfoSTCContext . Default . StorageInfoSTC , CancellationToken , new KeyValuePair < string , string? > ( "storage_id" , Storage . StorageID . ToString ( ) ) ) ;
}
Console . WriteLine ( "Offline Data Info: " + DateTime . UtcNow . Subtract ( dt ) . ToString ( "g" ) ) ;
if ( data . Update )
{
EncryptionHandler . Hash = Storage . UpdateStorage ( Convert . FromBase64String ( data . Password ) ) ;
_ = await SendServerPatch ( "OfflineData/Info" ,
new StorageInfoCTS ( )
{
Password = Convert . ToBase64String ( Encryption . AES . Encrypt ( EncryptionHandler . Hash , Storage . GetResourceBytes ( StorageDirectory . StorageInfo , "lpk" ) ) )
} ,
StorageInfoCTSContext . Default . StorageInfoCTS ,
StorageInfoSTCContext . Default . StorageInfoSTC , CancellationToken ,
new KeyValuePair < string , string? > ( "storage_id" , Storage . StorageID . ToString ( ) ) ) ;
Console . WriteLine ( "Data Update: " + DateTime . UtcNow . Subtract ( dt ) . ToString ( "g" ) ) ;
}
2023-08-21 10:58:17 -04:00
}
2024-03-20 23:18:34 -04:00
catch ( Exception e )
2023-08-21 10:58:17 -04:00
{
2024-03-20 23:18:34 -04:00
FailedSystems . Add ( new ( "Data Storage" , e . Message , e ) ) ;
2023-08-21 10:58:17 -04:00
}
2024-03-20 23:18:34 -04:00
#endregion
2023-08-21 10:58:17 -04:00
2024-03-20 23:18:34 -04:00
#region Key Generation
try
2023-08-21 10:58:17 -04:00
{
2024-03-20 23:18:34 -04:00
try
{
_ = EncryptionHandler . GetKey ( 0 ) ;
}
catch ( Exception e )
{
EncryptionHandler . SetKey ( 0 , new ( )
2023-08-21 10:58:17 -04:00
{
2024-03-20 23:18:34 -04:00
EncryptionType = EncryptionType . None ,
Key = string . Empty
} ) ;
Console . WriteLine ( "Key 0: " + DateTime . UtcNow . Subtract ( dt ) . ToString ( "g" ) ) ;
}
}
catch ( Exception e )
{
FailedSystems . Add ( new ( "Key Generation" , "Key 0 Failed to generate" , e ) ) ;
2023-08-21 10:58:17 -04:00
}
2024-03-20 23:18:34 -04:00
#endregion
#region Auto Status
2023-08-21 10:58:17 -04:00
try
{
2024-03-20 23:18:34 -04:00
_ = await UpdateStatus ( UserStatus . Online , CancellationToken ) ;
Console . WriteLine ( "Status: " + DateTime . UtcNow . Subtract ( dt ) . ToString ( "g" ) ) ;
2023-08-21 10:58:17 -04:00
}
catch ( Exception e )
{
2024-03-20 23:18:34 -04:00
FailedSystems . Add ( new ( "Auto Status" , "Failed to set status on the server" , e ) ) ;
2023-08-21 10:58:17 -04:00
}
2024-03-20 23:18:34 -04:00
#endregion
2024-03-31 23:57:12 -04:00
#region GetRoles
try
{
_ = await GetRoles ( ) ;
}
catch ( Exception e )
{
FailedSystems . Add ( new ( "Get Roles" , "Failed to get roles on the server" , e ) ) ;
}
#endregion
2024-03-20 23:18:34 -04:00
#region Local Storage Cleanup
try
2023-08-21 10:58:17 -04:00
{
2024-03-20 23:18:34 -04:00
KeyValuePair < string , string? > stor = new ( "storage_id" , Storage . StorageID . ToString ( ) ) ;
OfflineDataBlobSTC offlinedata = await GetFromServer ( "OfflineData" , OfflineDataBlobSTCContext . Default . OfflineDataBlobSTC , CancellationToken , stor ) ;
Console . WriteLine ( "Offline Data: " + DateTime . UtcNow . Subtract ( dt ) . ToString ( "g" ) ) ;
if ( offlinedata is not null & & offlinedata . Error is null & & offlinedata . Data is not null & & offlinedata . Data . Length > 0 )
2023-08-21 10:58:17 -04:00
{
2024-03-20 23:18:34 -04:00
string pkey = Storage . GetResourceKeyRaw (
StorageDirectory . ServerKeys ,
"pkey" ,
EncryptionHandler . Hash
) ;
foreach ( string keyexx in offlinedata . Data )
2023-08-21 10:58:17 -04:00
{
2024-03-20 23:18:34 -04:00
string keyex = Encoding . UTF8 . GetString ( Convert . FromBase64String ( keyexx ) ) ;
KeyExchange ? okd = JsonSerializer . Deserialize < KeyExchange > ( keyex ) ;
if ( okd is not null & & ! string . IsNullOrEmpty ( okd . key ) )
{
Storage . SetResourceKey (
StorageDirectory . ServerKeys ,
okd . id . ToString ( ) ,
EncryptionHandler . Hash ,
Encoding . Unicode . GetString (
Encryption . RSA . Decrypt (
Convert . FromBase64String ( okd . key ) ,
pkey
)
2023-08-21 10:58:17 -04:00
)
2024-03-20 23:18:34 -04:00
) ;
}
2023-08-21 10:58:17 -04:00
}
}
2024-03-20 23:18:34 -04:00
System . IO . File . WriteAllText ( "LastPassVer.txt" , EncryptionHandler . PasswordVersion . ToString ( ) ) ;
Storage . SetResourceKey ( StorageDirectory . ServerKeys , "pkey" , EncryptionHandler . Hash , EncryptionHandler . OfflinePrivateKey ) ;
KeyPostCTS OfflineKeySetRequest = new ( )
{
Data = Convert . ToBase64String ( Encoding . UTF8 . GetBytes ( EncryptionHandler . OfflinePublicKey ) ) ,
EncryptionType = EncryptionType . RSA
} ;
_ = await SendServer ( "Keys/SetOfflineKey" ,
OfflineKeySetRequest ,
KeyPostCTSContext . Default . KeyPostCTS ,
STCContext . Default . STC ,
CancellationToken . None ,
stor ) ;
Console . WriteLine ( "Offline Key: " + DateTime . UtcNow . Subtract ( dt ) . ToString ( "g" ) ) ;
EncryptionHandler . OfflinePublicKey = null ! ;
EncryptionHandler . OfflinePrivateKey = null ! ;
2023-08-21 10:58:17 -04:00
}
2024-03-20 23:18:34 -04:00
catch ( Exception e )
2023-08-21 10:58:17 -04:00
{
2024-03-20 23:18:34 -04:00
FailedSystems . Add ( new ( "Local Storage Cleanup" , "Failed to clean the local storage" , e ) ) ;
}
#endregion
if ( FailedSystems . Count > 0 )
{
Console . WriteLine ( "Some systems have failed:" ) ;
foreach ( Tuple < string , string , Exception > System in FailedSystems )
{
Console . WriteLine ( $"\t{System.Item1}:\n\t\tMessage: {System.Item2}\n\t\tError Details: {System.Item3}" ) ;
}
} } ) ;
#endregion
2023-08-21 10:58:17 -04:00
return true ;
}
else throw new Exception ( json ? . ErrorMessage ) ;
return true ;
}
}