Innovenergy_trunk/csharp/App/Backend/Database/User.cs

190 lines
5.5 KiB
C#
Raw Normal View History

using System.Diagnostics.CodeAnalysis;
2023-03-09 08:05:59 +00:00
using System.Net.Http.Headers;
2023-02-16 12:57:06 +00:00
using System.Net.Mail;
2023-02-22 13:46:36 +00:00
using System.Security.Cryptography;
2023-02-16 14:08:50 +00:00
using System.Text;
using System.Text.Json.Nodes;
2023-03-09 08:05:59 +00:00
using System.Text.RegularExpressions;
2023-02-22 13:46:36 +00:00
using Flurl.Http;
2023-03-08 12:20:33 +00:00
using InnovEnergy.App.Backend.Model;
using InnovEnergy.App.Backend.Utils;
2023-02-22 13:46:36 +00:00
using InnovEnergy.Lib.Utils;
2023-02-16 12:57:06 +00:00
using SQLite;
2023-03-09 08:05:59 +00:00
using ResponseExtensions = Flurl.Http.ResponseExtensions;
2023-02-24 11:58:47 +00:00
2023-02-16 12:57:06 +00:00
#pragma warning disable CS0472
#pragma warning disable CS8602
2023-03-08 12:20:33 +00:00
namespace InnovEnergy.App.Backend.Database;
2023-02-16 12:57:06 +00:00
public partial class Db
{
private TableQuery<User> Users => _Db.Table<User>();
public Int32 NbUsers => Users.Count();
public User? GetUserById(Int64 id)
{
2023-02-24 11:58:47 +00:00
return Users.FirstOrDefault(u => u.Id == id);
2023-02-16 12:57:06 +00:00
}
2023-02-24 11:58:47 +00:00
2023-02-16 12:57:06 +00:00
public Boolean IsParentOfChild(User parent, User child)
{
2023-03-09 09:52:31 +00:00
return child
.Unfold(GetParent)
.Any(u => u.Id == parent.Id);
}
public User? GetParent(User u)
{
return GetUserById(u.ParentId);
2023-02-16 12:57:06 +00:00
}
public User? GetUserByEmail(String email) => Users.FirstOrDefault(u => u.Email == email);
public Result CreateUser(User user)
{
if (GetUserByEmail(user.Email) is not null)
return Result.Error("User with that email already exists");
2023-02-24 11:58:47 +00:00
2023-02-16 14:08:50 +00:00
//Salting and Hashing password
var salt = Crypto.GenerateSalt();
2023-02-24 11:58:47 +00:00
var hashedPassword = Crypto.ComputeHash(Encoding.UTF8.GetBytes(user.Password),
2023-02-16 14:08:50 +00:00
Encoding.UTF8.GetBytes(salt + "innovEnergy"));
user.Salt = salt;
user.Password = hashedPassword;
2023-02-16 12:57:06 +00:00
2023-02-16 14:08:50 +00:00
return Create(user);
2023-02-16 12:57:06 +00:00
}
2023-02-24 11:58:47 +00:00
2023-03-09 08:05:59 +00:00
private static Byte[] HmacSha256Digest(String message, String secret)
{
var encoding = new UTF8Encoding();
var keyBytes = encoding.GetBytes(secret);
var messageBytes = encoding.GetBytes(message);
var cryptographer = new HMACSHA256(keyBytes);
var bytes = cryptographer.ComputeHash(messageBytes);
return bytes;
}
public String BuildSignature(String method, String path, String data, Int64 time, String secret)
{
var messageToSign = "";
messageToSign += method + " /v2/" + path + "\n";
messageToSign += data + "\n";
// query strings
messageToSign += "\n";
// headers
messageToSign += "\n";
messageToSign += time;
Console.WriteLine("Message to sign:\n" + messageToSign);
var hmac = HmacSha256Digest(messageToSign, secret);
return Convert.ToBase64String(hmac);
}
2023-02-22 13:46:36 +00:00
public Object CreateAndSaveUserS3ApiKey(User user)
{
//EXOSCALE API URL
2023-03-09 08:05:59 +00:00
const String url = "https://api-ch-dk-2.exoscale.com/v2/";
const String path = "access-key";
2023-02-22 13:46:36 +00:00
const String secret = "S2K1okphiCSNK4mzqr4swguFzngWAMb1OoSlZsJa9F0";
const String apiKey = "EXOb98ec9008e3ec16e19d7b593";
2023-02-24 11:58:47 +00:00
var installationList = User2Installation
2023-02-22 13:46:36 +00:00
.Where(i => i.UserId == user.Id)
.SelectMany(i => Installations.Where(f => i.InstallationId == f.Id))
.ToList();
2023-02-24 11:58:47 +00:00
var instList = new JsonArray();
foreach (var installation in installationList)
2023-02-22 13:46:36 +00:00
{
instList.Add(new JsonObject {["domain"] = "sos",["resource-name"] = installation.Name,["resource-type"] = "bucket"});
2023-02-22 13:46:36 +00:00
}
2023-03-09 08:05:59 +00:00
var jsonPayload = new JsonObject { ["name"] = user.Email, ["operations"] = new JsonArray{ "list-sos-bucket", "get-sos-object" }, ["content"] = instList};
var stringPayload = jsonPayload.ToJsonString();
2023-03-09 08:05:59 +00:00
var unixExpiration = DateTimeOffset.UtcNow.ToUnixTimeSeconds()+60;
var signature = BuildSignature("POST", path, stringPayload, unixExpiration , secret);
var authHeader = "credential="+apiKey+",expires="+unixExpiration+",signature="+signature;
2023-03-09 08:05:59 +00:00
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("EXO2-HMAC-SHA256", authHeader);
var content = new StringContent(stringPayload, Encoding.UTF8, "application/json");
var response = client.PostAsync(url+path, content).Result;
2023-02-28 11:34:36 +00:00
2023-03-09 08:05:59 +00:00
if (response.StatusCode.ToString() != "OK")
{
return response;
}
var responseString = response.Content.ReadAsStringAsync().Result;
var newKey = Enumerable.Last(Regex.Match(responseString, "key\\\":\\\"([A-Z])\\w+").ToString().Split('"'));
return SetUserS3ApiKey(user, newKey);
2023-02-28 11:34:36 +00:00
2023-02-22 13:46:36 +00:00
}
2023-02-24 11:58:47 +00:00
public Result SetUserS3ApiKey(User user, String key)
2023-02-22 13:46:36 +00:00
{
user.S3Key = key;
return Update(user);
}
2023-02-24 11:58:47 +00:00
2023-02-16 12:57:06 +00:00
public Result UpdateUser(User user)
{
var oldUser = GetUserById(user.Id);
if (oldUser == null)
return Result.Error("User doesn't exist");
//Checking for unchangeable things
// TODO: depends on privileges of caller
2023-02-24 11:58:47 +00:00
user.Id = oldUser.Id;
2023-02-16 12:57:06 +00:00
user.ParentId = oldUser.ParentId;
2023-02-24 11:58:47 +00:00
user.Email = oldUser.Email;
2023-02-16 12:57:06 +00:00
return Update(user);
}
public Result DeleteUser(User user)
{
2023-02-24 11:58:47 +00:00
User2Folder.Delete(u => u.UserId == user.Id);
User2Installation.Delete(u => u.UserId == user.Id);
2023-02-24 11:58:47 +00:00
2023-02-16 14:08:50 +00:00
//Todo check for orphaned Installations/Folders
2023-02-24 11:58:47 +00:00
// GetChildUsers()
2023-02-24 11:58:47 +00:00
2023-02-16 12:57:06 +00:00
return Delete(user);
}
2023-02-24 11:58:47 +00:00
2023-02-16 12:57:06 +00:00
// TODO
private static Boolean IsValidEmail(String email)
{
try
2023-02-24 11:58:47 +00:00
{
2023-02-16 12:57:06 +00:00
var emailAddress = new MailAddress(email);
}
catch
{
return false;
}
2023-02-24 11:58:47 +00:00
2023-02-16 12:57:06 +00:00
return true;
}
2023-02-24 11:58:47 +00:00
}