Skip to content

Commit

Permalink
Merge pull request #42 from Elagoht:feat/multi-users
Browse files Browse the repository at this point in the history
Main
  • Loading branch information
Elagoht authored Aug 5, 2024
2 parents 7129332 + 7062375 commit 76288a6
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 181 deletions.
19 changes: 16 additions & 3 deletions src/BusinessLogic/Authorization.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.IdentityModel.Tokens.Jwt;
using System.Text;
using Microsoft.IdentityModel.Tokens;

namespace Passenger
{
class Authorization(string secretKey)
Expand All @@ -14,6 +15,10 @@ public string GenerateToken(string username, string passphrase)
{
IssuedAt = DateTime.UtcNow,
Issuer = "passenger-cli",
Claims = new Dictionary<string, object>
{
{ "username", username }
},
TokenType = "Bearer",
Expires = DateTime.UtcNow.AddMinutes(10),
SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature)
Expand Down Expand Up @@ -46,14 +51,16 @@ public bool ValidateToken(string token)

public static bool ValidatePassphrase(string username, string passphrase)
{
Database database = new(username);

// TODO: This is a placeholder for a more complex validation algorithm
if (!Database.IsRegistered())
if (!database.IsRegistered())
{
Console.WriteLine("passenger: not registered yet");
Environment.Exit(1);
}
string passphraseOnDB = Database.GetCredentials().Passphrase;
string usernameOnDB = Database.GetCredentials().Username;
string passphraseOnDB = database.GetCredentials().Passphrase;
string usernameOnDB = database.GetCredentials().Username;

if (passphraseOnDB != passphrase || usernameOnDB != username)
{
Expand All @@ -62,5 +69,11 @@ public static bool ValidatePassphrase(string username, string passphrase)
}
return true;
}

public static string GetUserName(string token) =>
new JwtSecurityTokenHandler(
).ReadJwtToken(token
).Claims.First(claim => claim.Type == "username"
).Value;
}
}
9 changes: 0 additions & 9 deletions src/BusinessLogic/Validate.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,6 @@ public static bool EntryFields(ReadWritableDatabaseEntry databaseEntry) =>
_ => true
};

public static void ConstantPair(ConstantPair entry, bool checkExistence = true)
{
// Check if required fields are provided
if (string.IsNullOrEmpty(entry.Key)) Error.MissingField("key");
if (string.IsNullOrEmpty(entry.Value)) Error.MissingField("value");
if (!checkExistence) return;
if (Database.FetchConstant(entry.Key) != null) Error.ConstantExists(entry);
}

public static ReadWritableDatabaseEntry JsonAsDatabaseEntry(string json)
{
try { return JsonSerializer.Deserialize<ReadWritableDatabaseEntry>(json); }
Expand Down
89 changes: 10 additions & 79 deletions src/BusinessLogic/Worker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,19 @@ public class Worker(string[] args, string piped)
private readonly Authorization authorization = new(EnDeCoder.JSWSecret);
private readonly string[] arguments = args.Skip(1).ToArray();
private readonly string piped = piped;
private Database Database;

private void RoutineAuthControl(string verbName, int minOrActual, int max = -1)
{
string token = Environment.GetEnvironmentVariable("JWT");

if (arguments.Length < minOrActual || (max != -1 && arguments.Length > max))
Error.ArgumentCount(verbName, minOrActual, max);
if (!authorization.ValidateToken(
Environment.GetEnvironmentVariable("JWT")
)) Error.InvalidToken();
if (!authorization.ValidateToken(token))
Error.InvalidToken();

// Initialize database
Database = new Database(Authorization.GetUserName(token));
}

private void RequirePipedInput()
Expand All @@ -36,6 +41,8 @@ public void Login()
public void Register()
{
if (arguments.Length != 2) Error.ArgumentCount("register", 2);
// Routine control is not called here, so initialize database manually
Database = new Database(arguments[0]);
if (Database.IsRegistered())
Console.WriteLine("passenger: already registered");
else
Expand Down Expand Up @@ -179,55 +186,6 @@ public void Export()
));
}

/*
* Constant pairs
*/

public void Declare()
{
RoutineAuthControl("declare", 2);
ConstantPair constantPair = new()
{
Key = arguments[0],
Value = arguments[1]
};
Validate.ConstantPair(constantPair);
Database.DeclareConstant(constantPair);
}

public void Modify()
{
RoutineAuthControl("modify", 3);
ConstantPair newPair = new()
{
Key = arguments[1],
Value = arguments[2]
};
Database.ModifyConstant(arguments[0], newPair);
}

public void Remember()
{
RoutineAuthControl("remember", 1);
ConstantPair constantPair = Database.FetchConstant(arguments[0]);
if (constantPair == null) Error.EntryNotFound();
Console.WriteLine(JsonSerializer.Serialize(constantPair));
}

public void Forget()
{
RoutineAuthControl("forget", 1);
Database.ForgetConstant(arguments[0]);
}

public void Constants()
{
RoutineAuthControl("constants", 0);
Console.WriteLine(
JsonSerializer.Serialize(Database.AllConstants)
);
}

/*
* Generation
*/
Expand Down Expand Up @@ -345,28 +303,6 @@ Method can be bare or encrypted. Base64 encryption will be used.
Writes to stdout, can be redirected to a file.
JWT=[jwt] passenger export [method]
declare -D
Declare a new key-value pair, requires a JWT.
Theses pairs are constant values that can be replaced
on response.
JWT=[jwt] passenger declare [key] [value]
modify -M
Modify a key-value pair, requires a JWT.
JWT=[jwt] passenger modify [key] [value]
remember -R
Fetch a key-value pair, requires a JWT.
JWT=[jwt] passenger remember [key]
forget -F
Forget a key-value pair, requires a JWT.
JWT=[jwt] passenger forget [key]
constants -C
List all declared constants, requires a JWT.
JWT=[jwt] passenger constants
generate -g
Generate a passphrase with the given length.
Default length is 32.
Expand Down Expand Up @@ -426,11 +362,6 @@ passenger [command] [*args]
detect -d : detect issues about security of passphrases
import -i [browser] : import `chromium`, `firefox` or `safari` csv
export -e [method] : export to `bare` or `encrypted` csv
declare -D [key] [value] : declare a new key-value pair
modify -M [key] [value] : modify a key-value pair
remember -R [key] [value] : fetch a key-value pair
forget -F [key] : delete a key-value pair
constants -C : list all declared constants
generate -g [length] : generate a passphrase with the given length
manipulate -m [passphrase] : manipulate a passphrase
version -v --version : show the version and exit
Expand Down
83 changes: 23 additions & 60 deletions src/DataAccess/DataBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,19 @@

namespace Passenger
{
public static class Database
public class Database
{
static Database()
private readonly string databaseFile;
private readonly DatabaseModel database;

public Database(string username)
{
try
{
databaseFile = Path.Combine(
OperatingSystem.StoragePath,
$"{username}.bus"
);
string data = File.Exists(databaseFile)
? FileSystem.Read(databaseFile)
: "{}";
Expand All @@ -21,10 +28,7 @@ static Database()
* Database file
*/

private static readonly string databaseFile = OperatingSystem.StoragePath;
private static readonly DatabaseModel database;

public static void SaveToFile()
public void SaveToFile()
{
try
{
Expand All @@ -42,26 +46,25 @@ public static void SaveToFile()
* Authorization methods
*/

public static Credentials GetCredentials() => new()
public Credentials GetCredentials() => new()
{
Username = database.Username,
Passphrase = database.Passphrase
};

public static bool IsRegistered() =>
public bool IsRegistered() =>
!string.IsNullOrEmpty(database.Passphrase) &&
!string.IsNullOrEmpty(database.Username);

public static void Register(string username, string passphrase)
public void Register(string username, string passphrase)
{
database.Passphrase = passphrase;
database.Username = username;
database.Entries = [];
database.Constants = [];
SaveToFile();
}

public static void ResetPassphrase(string oldPassphrase, string newPassphrase)
public void ResetPassphrase(string oldPassphrase, string newPassphrase)
{
if (database.Passphrase != oldPassphrase) Error.InvalidPassphrase();
database.Passphrase = newPassphrase;
Expand All @@ -72,7 +75,7 @@ public static void ResetPassphrase(string oldPassphrase, string newPassphrase)
* CRUD operations
*/

public static ListableDatabaseEntry Create(ReadWritableDatabaseEntry entry)
public ListableDatabaseEntry Create(ReadWritableDatabaseEntry entry)
{
Validate.Entry(entry);
DatabaseEntry savedEntry = Mapper.CreateDatabaseEntry(
Expand All @@ -85,7 +88,7 @@ public static ListableDatabaseEntry Create(ReadWritableDatabaseEntry entry)
}

/// <summary>Prevents re-reading and re-crypting the database file</summary>
public static string Import(List<DatabaseEntry> entries)
public string Import(List<DatabaseEntry> entries)
{
try
{
Expand All @@ -99,23 +102,23 @@ public static string Import(List<DatabaseEntry> entries)
catch { Error.ImportFailed(); throw; }
}

public static List<ListableDatabaseEntry> FetchAll() =>
public List<ListableDatabaseEntry> FetchAll() =>
database.Entries.Select(
Mapper.ToListable
).ToList();

public static DatabaseEntry Fetch(string id) =>
public DatabaseEntry Fetch(string id) =>
database.Entries.Find(entry => entry.Id == id);

public static List<ListableDatabaseEntry> Query(string keyword) =>
public List<ListableDatabaseEntry> Query(string keyword) =>
database.Entries.Where(entry =>
(entry.Platform != null && entry.Platform.Contains(keyword)) ||
(entry.Identity != null && entry.Identity.Contains(keyword)) ||
(entry.Url != null && entry.Url.Contains(keyword))
).Select(Mapper.ToListable
).ToList();

public static ListableDatabaseEntry Update(string id, ReadWritableDatabaseEntry updatedEntry, bool preserveUpdatedAt = true)
public ListableDatabaseEntry Update(string id, ReadWritableDatabaseEntry updatedEntry, bool preserveUpdatedAt = true)
{
int index = database.Entries.FindIndex(entry => entry.Id == id);
if (index == -1) Error.EntryNotFound();
Expand Down Expand Up @@ -148,59 +151,19 @@ public static ListableDatabaseEntry Update(string id, ReadWritableDatabaseEntry
return Mapper.ToListable(existingEntry);
}

public static void Delete(string id)
public void Delete(string id)
{
database.Entries.RemoveAll(entry => entry.Id == id);
SaveToFile();
}

/*
* Constants pair methods
*/

public static ConstantPair DeclareConstant(ConstantPair entry)
{
Validate.ConstantPair(entry);
database.Constants ??= [];
database.Constants.Add(entry);
SaveToFile();
return entry;
}

public static ConstantPair FetchConstant(string constant) =>
(database.Constants ?? []).Find(pair =>
pair.Key == constant
);

public static ConstantPair ModifyConstant(string key, ConstantPair newPair)
{
if (FetchConstant(key) == null) Error.EntryNotFound();
Validate.ConstantPair(newPair, false);
database.Constants[database.Constants.FindIndex(pair =>
pair.Key == key
)] = newPair;
SaveToFile();
return newPair;
}

public static void ForgetConstant(string constant)
{
if (FetchConstant(constant) == null) Error.EntryNotFound();
database.Constants.RemoveAll((pair) =>
pair.Key == constant
);
SaveToFile();
}

/*
* Getters
*/

public static List<ConstantPair> AllConstants => database.Constants ?? [];

public static List<DatabaseEntry> AllEntries => database.Entries;
public List<DatabaseEntry> AllEntries => database.Entries;

public static List<ReadWritableDatabaseEntry> AllReadWritableEntries =>
public List<ReadWritableDatabaseEntry> AllReadWritableEntries =>
database.Entries.Select(
Mapper.ToReadWritable
).ToList();
Expand Down
7 changes: 1 addition & 6 deletions src/DataAccess/Mapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public static class Mapper
{
Id = entry.Id,
Platform = entry.Platform,
Identity = ResolveConstant(entry.Identity),
Identity = entry.Identity,
Url = entry.Url,
Created = entry.Created,
Updated = entry.Updated,
Expand All @@ -43,11 +43,6 @@ public static class Mapper
Url = entry.Url
};

public static string ResolveConstant(string key) =>
Database.AllConstants.Find((pair) =>
$"_${pair.Key}" == key
)?.Value ?? key;

public static string ToCSVLine(ReadWritableDatabaseEntry entry) =>
$"{entry.Platform},{entry.Url},{entry.Identity},{entry.Passphrase},{entry.Notes}";

Expand Down
Loading

0 comments on commit 76288a6

Please sign in to comment.