diff --git a/csharp/App/Backend/Backend.csproj b/csharp/App/Backend/Backend.csproj
index f990e5c8a..78c8036ca 100644
--- a/csharp/App/Backend/Backend.csproj
+++ b/csharp/App/Backend/Backend.csproj
@@ -3,6 +3,7 @@
+
@@ -26,14 +27,16 @@
-
-
-
-
PreserveNewest
+
+
+ Never
+
+
+
diff --git a/csharp/App/Backend/Controllers/Controller.cs b/csharp/App/Backend/Controllers/Controller.cs
index 198edf861..6cece6018 100644
--- a/csharp/App/Backend/Controllers/Controller.cs
+++ b/csharp/App/Backend/Controllers/Controller.cs
@@ -2,7 +2,6 @@ using InnovEnergy.App.Backend.Database;
using InnovEnergy.App.Backend.DataTypes;
using InnovEnergy.App.Backend.DataTypes.Methods;
using InnovEnergy.App.Backend.Relations;
-using InnovEnergy.Lib.Utils;
using Microsoft.AspNetCore.Mvc;
namespace InnovEnergy.App.Backend.Controllers;
@@ -17,11 +16,19 @@ public class Controller : ControllerBase
public ActionResult Login(String username, String password)
{
var user = Db.GetUserByName(username);
-
- if (user is null || !user.VerifyPassword(password))
+
+ if (user is null)
return Unauthorized();
+ if (!(user.Password is null && user.MustResetPassword))
+ {
+ if (!user.VerifyPassword(password))
+ return Unauthorized();
+ }
+
var session = new Session(user);
+
+ //TODO The Frontend should check for the MustResetPassword Flag
return Db.Create(session)
? session
@@ -106,7 +113,7 @@ public class Controller : ControllerBase
.Ancestors()
.SelectMany(f => f.UsersWithDirectAccess()
.Where(u => u.IsDescendantOf(user))
- .Select(u => new { folderId = f.Id, user = u }))
+ .Select(u => new { folderId = f.Id, folderName = f.Name, user = u }))
.ToList();
}
@@ -144,7 +151,7 @@ public class Controller : ControllerBase
.Ancestors()
.SelectMany(f => f.UsersWithDirectAccess()
.Where(u => u.IsDescendantOf(user))
- .Select(u => new { folderId = f.Id, user = u }))
+ .Select(u => new { folderId = f.Id, folderName = f.Name, user = u }))
.ToList();
}
@@ -317,6 +324,18 @@ public class Controller : ControllerBase
}
+ [HttpPut(nameof(UpdatePassword))]
+ public ActionResult UpdatePassword(String newPassword, Token authToken)
+ {
+ var session = Db.GetSession(authToken);
+
+ return session.UpdatePassword(newPassword)
+ ? Ok()
+ : Unauthorized();
+ }
+
+
+
[HttpPut(nameof(UpdateInstallation))]
public ActionResult UpdateInstallation(Installation installation, Token authToken)
{
@@ -340,6 +359,26 @@ public class Controller : ControllerBase
return folder;
}
+ [HttpPut(nameof(MoveInstallation))]
+ public ActionResult MoveInstallation(Int64 installationId,Int64 parentId, Token authToken)
+ {
+ var session = Db.GetSession(authToken);
+
+ return session.MoveInstallation(installationId, parentId)
+ ? Ok()
+ : Unauthorized();
+ }
+
+ [HttpPut(nameof(MoveFolder))]
+ public ActionResult MoveFolder(Int64 folderId,Int64 parentId, Token authToken)
+ {
+ var session = Db.GetSession(authToken);
+
+ return session.MoveFolder(folderId, parentId)
+ ? Ok()
+ : Unauthorized();
+ }
+
[HttpDelete(nameof(DeleteUser))]
public ActionResult DeleteUser(Int64 userId, Token authToken)
{
diff --git a/csharp/App/Backend/DataTypes/DeletedFolder.cs b/csharp/App/Backend/DataTypes/DeletedFolder.cs
new file mode 100644
index 000000000..a0193ab42
--- /dev/null
+++ b/csharp/App/Backend/DataTypes/DeletedFolder.cs
@@ -0,0 +1,6 @@
+namespace InnovEnergy.App.Backend.DataTypes;
+
+public class DeletedFolder : TreeNode {}
+
+//Deleted Things need to have AT LEAST every property that normal things have
+//Todo "Restore" Function? -k
\ No newline at end of file
diff --git a/csharp/App/Backend/DataTypes/DeletedInstallation.cs b/csharp/App/Backend/DataTypes/DeletedInstallation.cs
new file mode 100644
index 000000000..eb0846056
--- /dev/null
+++ b/csharp/App/Backend/DataTypes/DeletedInstallation.cs
@@ -0,0 +1,19 @@
+namespace InnovEnergy.App.Backend.DataTypes;
+
+//Deleted Things need to have AT LEAST every property that normal things have
+public class DeletedInstallation : TreeNode
+{
+ public String Location { get; set; } = "";
+ public String Region { get; set; } = "";
+ public String Country { get; set; } = "";
+
+ // TODO: make relation
+ public String OrderNumbers { get; set; } = "";
+
+ public Double Lat { get; set; }
+ public Double Long { get; set; }
+
+ public String S3Bucket { get; set; } = "";
+ public String S3Url { get; set; } = "";
+
+}
\ No newline at end of file
diff --git a/csharp/App/Backend/DataTypes/DeletedUser.cs b/csharp/App/Backend/DataTypes/DeletedUser.cs
new file mode 100644
index 000000000..4f82c06a8
--- /dev/null
+++ b/csharp/App/Backend/DataTypes/DeletedUser.cs
@@ -0,0 +1,22 @@
+using SQLite;
+
+namespace InnovEnergy.App.Backend.DataTypes;
+
+
+//Deleted Things need to have AT LEAST every property that normal things have
+
+public class DeletedUser : TreeNode
+{
+ public String Email { get; set; } = null!;
+ public Boolean HasWriteAccess { get; set; } = false;
+ public Boolean MustResetPassword { get; set; } = false;
+ public String Language { get; set; } = null!;
+ public String Password { get; set; } = null!;
+
+ [Unique]
+ public override String Name { get; set; } = null!;
+
+
+
+ // TODO: must reset pwd
+}
\ No newline at end of file
diff --git a/csharp/App/Backend/DataTypes/Methods/Folder.cs b/csharp/App/Backend/DataTypes/Methods/Folder.cs
index ee93eeab8..10e8d41c2 100644
--- a/csharp/App/Backend/DataTypes/Methods/Folder.cs
+++ b/csharp/App/Backend/DataTypes/Methods/Folder.cs
@@ -23,6 +23,17 @@ public static class FolderMethods
.NotNull();
}
+ public static DeletedFolder ToDeletedFolder(this Folder folder)
+ {
+ var deletedFolder = new DeletedFolder();
+ foreach (var property in folder.GetType().GetProperties())
+ {
+ property.SetValue(deletedFolder,property.GetValue(folder));
+ }
+
+ return deletedFolder;
+ }
+
public static IEnumerable UsersWithInheritedAccess(this Folder folder)
{
return folder
diff --git a/csharp/App/Backend/DataTypes/Methods/Installation.cs b/csharp/App/Backend/DataTypes/Methods/Installation.cs
index d9fc72728..3dc908d09 100644
--- a/csharp/App/Backend/DataTypes/Methods/Installation.cs
+++ b/csharp/App/Backend/DataTypes/Methods/Installation.cs
@@ -20,7 +20,8 @@ public static class InstallationMethods
}
public static async Task RenewS3BucketUrl(this Installation installation, TimeSpan validity)
- {
+ {
+ installation.S3Url =
installation.S3Url = await S3Access.ReadOnly.SignUrl(installation.BucketName(), validity);
return Db.Update(installation);
}
@@ -61,6 +62,17 @@ public static class InstallationMethods
.SelectMany(f => f.UsersWithDirectAccess())
.NotNull();
}
+
+ public static DeletedInstallation ToDeletedInstallation(this Installation installation)
+ {
+ var deletedInstallation = new DeletedInstallation();
+ foreach (var property in installation.GetType().GetProperties())
+ {
+ property.SetValue(deletedInstallation ,property.GetValue(installation));
+ }
+
+ return deletedInstallation;
+ }
public static IEnumerable Ancestors(this Installation installation)
{
diff --git a/csharp/App/Backend/DataTypes/Methods/Session.cs b/csharp/App/Backend/DataTypes/Methods/Session.cs
index 5d5d2b4e7..5bbff344c 100644
--- a/csharp/App/Backend/DataTypes/Methods/Session.cs
+++ b/csharp/App/Backend/DataTypes/Methods/Session.cs
@@ -32,6 +32,38 @@ public static class SessionMethods
.WithParentOf(original) // prevent moving
.Apply(Db.Update);
}
+
+ public static Boolean MoveFolder(this Session? session, Int64 folderId, Int64 parentId)
+ {
+ var user = session?.User;
+ var folder = Db.GetFolderById(folderId);
+ var parent = Db.GetFolderById(parentId);
+
+ return user is not null
+ && folder is not null
+ && user.HasWriteAccess
+ && user.HasAccessTo(folder)
+ && user.HasAccessTo(parent)
+ && folder
+ .Do(() => folder.ParentId = parentId)
+ .Apply(Db.Update);
+ }
+
+ public static Boolean MoveInstallation(this Session? session, Int64 installationId, Int64 parentId)
+ {
+ var user = session?.User;
+ var installation = Db.GetInstallationById(installationId);
+ var parent = Db.GetFolderById(parentId);
+
+ return user is not null
+ && installation is not null
+ && user.HasWriteAccess
+ && user.HasAccessTo(installation)
+ && user.HasAccessTo(parent)
+ && installation
+ .Do(() => installation.ParentId = parentId)
+ .Apply(Db.Update);
+ }
public static Boolean Delete(this Session? session, Folder? folder)
{
@@ -41,6 +73,7 @@ public static class SessionMethods
&& folder is not null
&& user.HasWriteAccess
&& user.HasAccessTo(folder)
+ && Db.Create(folder.ToDeletedFolder())
&& Db.Delete(folder);
}
@@ -84,21 +117,27 @@ public static class SessionMethods
&& installation is not null
&& user.HasWriteAccess
&& user.HasAccessTo(installation)
- // && installation.DeleteBucket().Result // TODO
+ && Db.Create(installation.ToDeletedInstallation())
+ // && installation.DeleteBucket().Result // TODO
&& Db.Delete(installation);
}
public static Boolean Create(this Session? session, User? newUser)
{
var sessionUser = session?.User;
+
+ return sessionUser is not null
+ && newUser is not null
+ && sessionUser.HasWriteAccess
+ && newUser
+ .WithParent(sessionUser)
+ .Do(() => newUser.Password = newUser.SaltAndHashPassword(newUser.Password))
+ .Do(() => newUser.MustResetPassword = true)
+ .Apply(Db.Create)
+ && Mailer.Mailer.SendVerificationMessage(newUser);
+
+ //Send Email to new user to verify email and set password
- return sessionUser is not null
- && newUser is not null
- && sessionUser.HasWriteAccess
- && newUser
- .WithParent(sessionUser)
- .Do(() => newUser.Password = newUser.SaltAndHashPassword(newUser.Password))
- .Apply(Db.Create);
}
public static Boolean Update(this Session? session, User? editedUser)
@@ -116,6 +155,16 @@ public static class SessionMethods
.WithPasswordOf(originalUser)
.Apply(Db.Update);
}
+
+ public static Boolean UpdatePassword(this Session? session, String? newPassword)
+ {
+ var sessionUser = session?.User;
+
+ return sessionUser is not null
+ && sessionUser
+ .Do(() => sessionUser.Password = sessionUser.SaltAndHashPassword(newPassword))
+ .Apply(Db.Update);
+ }
public static Boolean Delete(this Session? session, User? userToDelete)
{
@@ -124,7 +173,8 @@ public static class SessionMethods
return sessionUser is not null
&& userToDelete is not null
&& sessionUser.HasWriteAccess
- && sessionUser.HasAccessTo(userToDelete)
+ && sessionUser.HasAccessTo(userToDelete)
+ && Db.Create(sessionUser.ToDeletedUser())
&& Db.Delete(userToDelete);
}
diff --git a/csharp/App/Backend/DataTypes/Methods/User.cs b/csharp/App/Backend/DataTypes/Methods/User.cs
index 5907b7c1e..4851c0d3f 100644
--- a/csharp/App/Backend/DataTypes/Methods/User.cs
+++ b/csharp/App/Backend/DataTypes/Methods/User.cs
@@ -97,9 +97,10 @@ public static class UserMethods
public static Boolean VerifyPassword(this User user, String password)
{
- return user.Password == user.SaltAndHashPassword(password);
+ return Db.GetUserWithPasswordByName(user.Name)?.Password == user.SaltAndHashPassword(password);
}
+
public static String SaltAndHashPassword(this User user, String password)
{
var dataToHash = $"{password}{user.Salt()}";
@@ -183,10 +184,27 @@ public static class UserMethods
user.Password = other.Password;
return user;
}
+
+ public static DeletedUser ToDeletedUser(this User user)
+ {
+ var deletedUser = new DeletedUser();
+ foreach (var property in user.GetType().GetProperties())
+ {
+ property.SetValue(deletedUser,property.GetValue(user));
+ }
+
+ return deletedUser;
+ }
+
+ public static User? HidePassword(this User? user)
+ {
+ if(user is not null)
+ user.Password = "";
+
+ return user;
+ }
+
-
-
-
// TODO?
private static Boolean IsValidEmail(String email)
{
diff --git a/csharp/App/Backend/DataTypes/User.cs b/csharp/App/Backend/DataTypes/User.cs
index 449285fe3..ca075eecb 100644
--- a/csharp/App/Backend/DataTypes/User.cs
+++ b/csharp/App/Backend/DataTypes/User.cs
@@ -6,11 +6,15 @@ public class User : TreeNode
{
public String Email { get; set; } = null!;
public Boolean HasWriteAccess { get; set; } = false;
+ public Boolean MustResetPassword { get; set; } = false;
public String Language { get; set; } = null!;
public String Password { get; set; } = null!;
[Unique]
public override String Name { get; set; } = null!;
+
+
// TODO: must reset pwd
+
}
\ No newline at end of file
diff --git a/csharp/App/Backend/Database/Create.cs b/csharp/App/Backend/Database/Create.cs
index 40b40cf2c..436ca6246 100644
--- a/csharp/App/Backend/Database/Create.cs
+++ b/csharp/App/Backend/Database/Create.cs
@@ -13,15 +13,30 @@ public static partial class Db
return Connection.Insert(installation) > 0;
}
+ public static Boolean Create(DeletedInstallation installation)
+ {
+ return Connection.Insert(installation) > 0;
+ }
+
public static Boolean Create(Folder folder)
{
return Connection.Insert(folder) > 0;
}
+ public static Boolean Create(DeletedFolder folder)
+ {
+ return Connection.Insert(folder) > 0;
+ }
+
public static Boolean Create(User user)
{
return Connection.Insert(user) > 0;
}
+
+ public static Boolean Create(DeletedUser user)
+ {
+ return Connection.Insert(user) > 0;
+ }
public static Boolean Create(Session session)
{
diff --git a/csharp/App/Backend/Database/Read.cs b/csharp/App/Backend/Database/Read.cs
index 5a4eae7bb..2cdc08d10 100644
--- a/csharp/App/Backend/Database/Read.cs
+++ b/csharp/App/Backend/Database/Read.cs
@@ -1,5 +1,7 @@
using InnovEnergy.App.Backend.DataTypes;
+using InnovEnergy.App.Backend.DataTypes.Methods;
using InnovEnergy.App.Backend.Relations;
+using InnovEnergy.Lib.Utils;
namespace InnovEnergy.App.Backend.Database;
@@ -21,14 +23,25 @@ public static partial class Db
public static User? GetUserById(Int64? id)
{
+ //TODO Sanitize Password here
return Users
- .FirstOrDefault(u => u.Id == id);
+ .FirstOrDefault(u => u.Id == id)
+ .HidePassword();
}
public static User? GetUserByName(String userName)
{
+ //TODO Sanitize Password here
return Users
- .FirstOrDefault(u => u.Name == userName);
+ .FirstOrDefault(u => u.Name == userName)
+ .HidePassword();
+ }
+
+ public static User? GetUserWithPasswordByName(String userName)
+ {
+ //TODO Sanitize Password here
+ return Users
+ .FirstOrDefault(u => u.Name == userName);
}
public static Session? GetSession(String token)
diff --git a/csharp/App/Backend/Mailer/Mailer.cs b/csharp/App/Backend/Mailer/Mailer.cs
new file mode 100644
index 000000000..b64a01a17
--- /dev/null
+++ b/csharp/App/Backend/Mailer/Mailer.cs
@@ -0,0 +1,35 @@
+using System;
+using InnovEnergy.App.Backend.DataTypes;
+using MailKit.Net.Smtp;
+using MailKit;
+using MimeKit;
+
+namespace InnovEnergy.App.Backend.Mailer;
+public static class Mailer
+ {
+ public static Boolean SendVerificationMessage (User emailRecipientUser)
+ {
+ var email = new MimeMessage();
+
+ email.From.Add(new MailboxAddress("InnovEnergy", "noreply@innov.energy"));
+ email.To.Add(new MailboxAddress(emailRecipientUser.Name, "fern95@ethereal.email"));
+
+ email.Subject = "Create a new password for your Innovenergy-Account";
+ email.Body = new TextPart(MimeKit.Text.TextFormat.Plain) {
+ Text = "Dear " + emailRecipientUser.Name + "\n Please create a new password for your Innovenergy-account." +
+ "\n To do this just login at https://HEEEEELP"
+ };
+ using (var smtp = new SmtpClient())
+ {
+ smtp.Connect("smtp.ethereal.email", 587, false);
+
+ // Todo put me into urlAndKey.json
+ smtp.Authenticate("fern95@ethereal.email", "dYKVnc4RQNEFckHaNV");
+
+ smtp.Send(email);
+ smtp.Disconnect(true);
+ }
+
+ return true;
+ }
+ }
diff --git a/csharp/App/Backend/Resources/urlAndKey.json b/csharp/App/Backend/Resources/urlAndKey.json
new file mode 100644
index 000000000..137c8e690
--- /dev/null
+++ b/csharp/App/Backend/Resources/urlAndKey.json
@@ -0,0 +1,6 @@
+{
+ "ReadOnlyS3Key": "EXO44d2979c8e570eae81ead564",
+ "ReadOnlyS3Secret": "55MAqyO_FqUmh7O64VIO0egq50ERn_WIAWuc2QC44QU" ,
+ "ReadWriteS3Key": "EXO87ca85e29dd412f1238f1cf0",
+ "ReadWriteS3Secret": "-T9TAqy9a3-0-xj7HKsFFJOCcxfRpcnL6OW5oOrOcWU"
+}
\ No newline at end of file
diff --git a/csharp/App/Backend/S3/S3Access.cs b/csharp/App/Backend/S3/S3Access.cs
index 0fe957ad5..912997a18 100644
--- a/csharp/App/Backend/S3/S3Access.cs
+++ b/csharp/App/Backend/S3/S3Access.cs
@@ -1,3 +1,6 @@
+using static System.IO.File;
+using static System.Text.Json.JsonSerializer;
+
namespace InnovEnergy.App.Backend.S3;
public static class S3Access
@@ -6,16 +9,16 @@ public static class S3Access
// there so they can be changed without recompiling
// they should be read from disk on each use,
// so the backend does not need to be restarted on change
-
+
public static S3Cmd ReadOnly { get; } = new S3Cmd
(
- key : "EXO44d2979c8e570eae81ead564",
- secret: "55MAqyO_FqUmh7O64VIO0egq50ERn_WIAWuc2QC44QU"
+ key : Deserialize>(OpenRead("./Resources/urlAndKey.json"))?["ReadOnlyS3Key"],
+ secret: Deserialize>(OpenRead("./Resources/urlAndKey.json"))?["ReadOnlyS3Secret"]
);
public static S3Cmd ReadWrite { get; } = new S3Cmd
(
- key : "EXO87ca85e29dd412f1238f1cf0",
- secret: "-T9TAqy9a3-0-xj7HKsFFJOCcxfRpcnL6OW5oOrOcWU"
+ key : Deserialize>(OpenRead("./Resources/urlAndKey.json"))?["ReadWriteS3Key"],
+ secret: Deserialize>(OpenRead("./Resources/urlAndKey.json"))?["ReadWriteS3Secret"]
);
}
\ No newline at end of file
diff --git a/csharp/App/Backend/S3/S3Cmd.cs b/csharp/App/Backend/S3/S3Cmd.cs
index b8bd8f890..8b2ad3e05 100644
--- a/csharp/App/Backend/S3/S3Cmd.cs
+++ b/csharp/App/Backend/S3/S3Cmd.cs
@@ -8,15 +8,15 @@ public class S3Cmd
{
private static readonly Command Python = Cli.Wrap("python3");
- private const String S3CmdPath = "Resources/s3cmd.py";
+ private const String? S3CmdPath = "Resources/s3cmd.py";
private const String S3Prefix = "s3://";
- private String[] DefaultArgs { get; }
+ private String?[] DefaultArgs { get; }
// ReSharper disable StringLiteralTypo
// ReSharper enable StringLiteralTypo
- public S3Cmd(String key, String secret)
+ public S3Cmd(String? key, String? secret)
{
DefaultArgs = new[]
{
diff --git a/csharp/App/Backend/db.sqlite b/csharp/App/Backend/db.sqlite
index 5ed0b4ad0..d79310ab5 100644
Binary files a/csharp/App/Backend/db.sqlite and b/csharp/App/Backend/db.sqlite differ