Compare commits
	
		
			4 Commits
		
	
	
		
			2f5f753ab6
			...
			bce48fe8d1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | bce48fe8d1 | ||
|  | 998cb90acc | ||
|  | 47797d18a0 | ||
|  | 6f311fabd4 | 
							
								
								
									
										92
									
								
								backend/Api/AMQP/AMQPPublisher.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								backend/Api/AMQP/AMQPPublisher.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,92 @@ | ||||
| using Api.DBAccess; | ||||
| using Api.Models; | ||||
| using RabbitMQ.Client; | ||||
| using RabbitMQ.Client.Events; | ||||
| using System.Text; | ||||
| using System.Text.Json; | ||||
| 
 | ||||
| namespace Api.AMQP | ||||
| { | ||||
|     public class AMQPPublisher | ||||
|     { | ||||
|         private readonly IConfiguration _configuration; | ||||
|         private readonly DbAccess _dbAccess; | ||||
| 
 | ||||
|         public AMQPPublisher(IConfiguration configuration, DbAccess dbAccess) | ||||
|         { | ||||
|             _dbAccess = dbAccess; | ||||
|             _configuration = configuration; | ||||
|         } | ||||
| 
 | ||||
|         public async Task Handle_Push_Device_Limits() | ||||
|         { | ||||
|             var factory = new ConnectionFactory(); | ||||
|             var queue = "temperature-limits"; | ||||
| 
 | ||||
|             factory.UserName = _configuration["AMQP:username"]; | ||||
|             factory.Password = _configuration["AMQP:password"]; | ||||
|             factory.HostName = _configuration["AMQP:host"]; | ||||
|             factory.Port = Convert.ToInt32(_configuration["AMQP:port"]); | ||||
| 
 | ||||
|             // Connecting to our rabbitmq and after that it create's a channel where you can connect to a queue | ||||
|             var conn = await factory.CreateConnectionAsync(); | ||||
|             Console.WriteLine("AMQPClient connected"); | ||||
|             var channel = await conn.CreateChannelAsync(); | ||||
| 
 | ||||
|             // Here we connect to the queue through the channel that got created earlier | ||||
|             await channel.QueueDeclareAsync(queue: queue, durable: false, exclusive: false, autoDelete: false); | ||||
|             Console.WriteLine($"{queue} connected"); | ||||
| 
 | ||||
|             while (true) | ||||
|             { | ||||
|                 // Publishes all devices limits | ||||
|                 var devices = _dbAccess.ReadDevices(); | ||||
|                 foreach (var device in devices) | ||||
|                 { | ||||
|                     var deviceLimit = new DeviceLimit(); | ||||
|                     deviceLimit.ReferenceId = device.ReferenceId; | ||||
|                     deviceLimit.TempHigh = device.TempHigh; | ||||
|                     deviceLimit.TempLow = device.TempLow; | ||||
|                     string message = JsonSerializer.Serialize(deviceLimit); | ||||
|                     var body = Encoding.UTF8.GetBytes(message); | ||||
|                     await channel.BasicPublishAsync(exchange: string.Empty, routingKey: queue, body: body); | ||||
|                 } | ||||
| 
 | ||||
|                 // Short delay before disconnecting from rabbitMQ | ||||
|                 await Task.Delay(10000); | ||||
| 
 | ||||
|                 // Disconnecting from rabbitMQ to save resources | ||||
|                 await channel.CloseAsync(); | ||||
|                 Console.WriteLine($"{queue} disconnected"); | ||||
|                 await conn.CloseAsync(); | ||||
|                 Console.WriteLine("AMQPClient disconnected"); | ||||
|                 await channel.DisposeAsync(); | ||||
|                 await conn.DisposeAsync(); | ||||
|                 // 1 hour delay | ||||
|                 await Task.Delay(3600000); | ||||
| 
 | ||||
|                 // Creating a new connection to rabbitMQ | ||||
|                 conn = await factory.CreateConnectionAsync(); | ||||
|                 Console.WriteLine("AMQPClient connected"); | ||||
|                 channel = await conn.CreateChannelAsync(); | ||||
| 
 | ||||
|                 // Here we connect to the queue through the channel that got created earlier | ||||
|                 await channel.QueueDeclareAsync(queue: queue, durable: false, exclusive: false, autoDelete: false); | ||||
|                 Console.WriteLine($"{queue} connected"); | ||||
| 
 | ||||
|                 // Here all messages is consumed so the queue is empty | ||||
|                 var consumer = new AsyncEventingBasicConsumer(channel); | ||||
|                 consumer.ReceivedAsync += (model, ea) => | ||||
|                 { | ||||
|                     Console.WriteLine("Emptying queue"); | ||||
| 
 | ||||
|                     return Task.CompletedTask; | ||||
|                 }; | ||||
| 
 | ||||
|                 // Consumes the data in the queue | ||||
|                 await channel.BasicConsumeAsync(queue, true, consumer); | ||||
| 
 | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -30,7 +30,7 @@ namespace Api.AMQPReciever | ||||
| 
 | ||||
|             // Connecting to our rabbitmq and after that it create's a channel where you can connect to a queue | ||||
|             using var conn = await factory.CreateConnectionAsync(); | ||||
|             Console.WriteLine("AMQPClien connected"); | ||||
|             Console.WriteLine("AMQPClient connected"); | ||||
|             using var channel = await conn.CreateChannelAsync(); | ||||
| 
 | ||||
|             // Here we connect to the queue through the channel that got created earlier | ||||
| @ -45,7 +45,7 @@ namespace Api.AMQPReciever | ||||
|                 var body = ea.Body.ToArray(); | ||||
|                 var message = Encoding.UTF8.GetString(body); | ||||
| 
 | ||||
|                 var messageReceive = JsonSerializer.Deserialize<MQTTMessageReceive>(message); | ||||
|                 var messageReceive = JsonSerializer.Deserialize<MessageReceive>(message); | ||||
| 
 | ||||
|                 // Checks if the message has the data we need | ||||
|                 if (messageReceive == null || messageReceive.device_id == null || messageReceive.timestamp == 0) | ||||
| @ -16,6 +16,12 @@ namespace Api.BusinessLogic | ||||
|             _configuration = configuration; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets the user from dbaccess using the userId and checks if the user exists | ||||
|         /// Gets all devices that match the userId and checks if there are any devices connected to the user | ||||
|         /// </summary> | ||||
|         /// <param name="userId">UserId that matches a user that owns the devices</param> | ||||
|         /// <returns>returns the devices in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns> | ||||
|         public async Task<IActionResult> GetDevices(int userId) | ||||
|         { | ||||
|             var profile = await _dbAccess.ReadUser(userId); | ||||
| @ -29,6 +35,13 @@ namespace Api.BusinessLogic | ||||
|             return new OkObjectResult(devices); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Checks if the user that the device is trying to be added to exists | ||||
|         /// Then it is send to dbaccess | ||||
|         /// </summary> | ||||
|         /// <param name="device">The new device</param> | ||||
|         /// <param name="userId">The user that owns the device</param> | ||||
|         /// <returns>returns true in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns> | ||||
|         public async Task<IActionResult> AddDevice(Device device, int userId) | ||||
|         { | ||||
|             var profile = await _dbAccess.ReadUser(userId); | ||||
| @ -38,6 +51,12 @@ namespace Api.BusinessLogic | ||||
|             return await _dbAccess.CreateDevice(device, userId); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Checks if the device exist that is trying to be read from | ||||
|         /// Gets the logs and checks if there are any in the list | ||||
|         /// </summary> | ||||
|         /// <param name="deviceId">The deviceId that you want from the logs</param> | ||||
|         /// <returns>returns the logs in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns> | ||||
|         public async Task<IActionResult> GetLogs(int deviceId) | ||||
|         { | ||||
|             var device = await _dbAccess.ReadDevice(deviceId); | ||||
| @ -51,6 +70,12 @@ namespace Api.BusinessLogic | ||||
|             return new OkObjectResult(logs); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Checks if the deviceId matches a device | ||||
|         /// </summary> | ||||
|         /// <param name="device">The updated info</param> | ||||
|         /// <param name="deviceId">The device to be edited</param> | ||||
|         /// <returns>returns the updated device in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns> | ||||
|         public async Task<IActionResult> EditDevice(Device device, int deviceId) | ||||
|         { | ||||
|             var device1 = _dbAccess.ReadDevice(deviceId); | ||||
|  | ||||
| @ -22,6 +22,14 @@ namespace Api.BusinessLogic | ||||
|             _configuration = configuration; | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// First checks if the mail is a valid one with regex so if there is something before the @ and after and it has a domain | ||||
|         /// Then it checks if the password is to our security standard | ||||
|         /// Then it makes sure the user has a device list | ||||
|         /// The last thing before it saves the user is creating a salt and then hashing of the password | ||||
|         /// </summary> | ||||
|         /// <param name="user">The new user</param> | ||||
|         /// <returns>returns true in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns> | ||||
|         public async Task<IActionResult> RegisterUser(User user) | ||||
|         { | ||||
|             if (!new Regex(@".+@.+\..+").IsMatch(user.Email)) | ||||
| @ -48,6 +56,13 @@ namespace Api.BusinessLogic | ||||
|             return await _dbAccess.CreateUser(user); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets the user that matches the login | ||||
|         /// Hashes the login password with the users salt | ||||
|         /// checks if the hashed password that the login has is the same as the one saved in the database | ||||
|         /// </summary> | ||||
|         /// <param name="login">Has a username or email and a password</param> | ||||
|         /// <returns>Returns a jwt token, username and userid</returns> | ||||
|         public async Task<IActionResult> Login(Login login) | ||||
|         { | ||||
|             User user = await _dbAccess.Login(login); | ||||
| @ -65,6 +80,15 @@ namespace Api.BusinessLogic | ||||
|             return new ConflictObjectResult(new { message = "Invalid password" }); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// First checks if the mail is a valid one with regex so if there is something before the @ and after and it has a domain | ||||
|         /// Then it checks if the password is to our security standard | ||||
|         /// Finds the user that matches the userId and hashes a new hash with the old salt | ||||
|         /// Then the updated user and the userId is being send to dbaccess | ||||
|         /// </summary> | ||||
|         /// <param name="user">Contains the updated user info</param> | ||||
|         /// <param name="userId">Has the id for the user that is to be updated</param> | ||||
|         /// <returns>returns the updated user in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns> | ||||
|         public async Task<IActionResult> EditProfile(User user, int userId) | ||||
|         { | ||||
|             if (!new Regex(@".+@.+\..+").IsMatch(user.Email)) | ||||
| @ -85,11 +109,23 @@ namespace Api.BusinessLogic | ||||
|             return await _dbAccess.UpdateUser(user, userId); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Just sends the userid of the user that is to be deleted | ||||
|         /// </summary> | ||||
|         /// <param name="userId">The Id of the user that is to be deleted</param> | ||||
|         /// <returns>returns the true in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns> | ||||
|         public async Task<IActionResult> DeleteUser(int userId) | ||||
|         { | ||||
|             return await _dbAccess.DeleteUser(userId); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Generates a hash from a salt and input using the algorithm that is provided | ||||
|         /// </summary> | ||||
|         /// <param name="input">This is the input that is supposed to be hashed</param> | ||||
|         /// <param name="algorithm">This is the alogorithm that is used to encrypt the input</param> | ||||
|         /// <param name="salt">This is something extra added to make the hashed input more unpredictable</param> | ||||
|         /// <returns>The hashed input</returns> | ||||
|         private static string ComputeHash(string input, HashAlgorithm algorithm, string salt) | ||||
|         { | ||||
|             Byte[] inputBytes = Encoding.UTF8.GetBytes(input); | ||||
| @ -105,6 +141,11 @@ namespace Api.BusinessLogic | ||||
|             return BitConverter.ToString(hashedBytes); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Checks if password is up to our security standard | ||||
|         /// </summary> | ||||
|         /// <param name="password">The password that is to be checked</param> | ||||
|         /// <returns>true or false dependeing on if the password is up to standard</returns> | ||||
|         public bool PasswordSecurity(string password) | ||||
|         { | ||||
|             var hasMinimum8Chars = new Regex(@".{8,}"); | ||||
| @ -112,6 +153,11 @@ namespace Api.BusinessLogic | ||||
|             return hasMinimum8Chars.IsMatch(password); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Generates a JWT token that last 2 hours | ||||
|         /// </summary> | ||||
|         /// <param name="user">Used for sending the userid and username with the token</param> | ||||
|         /// <returns>Returns a valid JWTToken</returns> | ||||
|         private string GenerateJwtToken(User user) | ||||
|         { | ||||
|             var claims = new[] | ||||
| @ -129,7 +175,7 @@ namespace Api.BusinessLogic | ||||
|                 _configuration["JwtSettings:Issuer"], | ||||
|                 _configuration["JwtSettings:Audience"], | ||||
|                 claims, | ||||
|                 expires: DateTime.Now.AddMinutes(30), | ||||
|                 expires: DateTime.Now.AddHours(2), | ||||
|                 signingCredentials: creds); | ||||
| 
 | ||||
|             return new JwtSecurityTokenHandler().WriteToken(token); | ||||
|  | ||||
| @ -19,15 +19,15 @@ namespace Api.Controllers | ||||
|             _deviceLogic = deviceLogic; | ||||
|         } | ||||
| 
 | ||||
|         // Sends the userId to deviceLogic | ||||
|         [Authorize] | ||||
|         [HttpGet("{userId}")] | ||||
|         public async Task<IActionResult> GetDevices(int userId) | ||||
|         { | ||||
|             List<Device> devices = await _dbAccess.ReadDevices(userId); | ||||
|             if (devices.Count == 0) { return BadRequest(new { error = "There is no devices that belong to this userID" }); } | ||||
|             return await _deviceLogic.GetDevices(userId); | ||||
|         } | ||||
| 
 | ||||
|         // Sends the device and userId to deviceLogic | ||||
|         [Authorize] | ||||
|         [HttpPost("adddevice/{userId}")] | ||||
|         public async Task<IActionResult> AddDevice([FromBody] Device device, int userId) | ||||
| @ -35,6 +35,7 @@ namespace Api.Controllers | ||||
|             return await _deviceLogic.AddDevice(device, userId); | ||||
|         } | ||||
| 
 | ||||
|         // Sends the deviceId to deviceLogic | ||||
|         [Authorize] | ||||
|         [HttpGet("logs/{deviceId}")] | ||||
|         public async Task<IActionResult> GetLogs(int deviceId) | ||||
| @ -42,6 +43,7 @@ namespace Api.Controllers | ||||
|             return await _deviceLogic.GetLogs(deviceId); | ||||
|         } | ||||
| 
 | ||||
|         // Sends the deviceId to deviceLogic | ||||
|         [Authorize] | ||||
|         [HttpPut("Edit/{deviceId}")] | ||||
|         public async Task<IActionResult> EditDevice([FromBody] Device device, int deviceId) | ||||
|  | ||||
| @ -21,18 +21,21 @@ namespace Api.Controllers | ||||
|             _userLogic = userLogic; | ||||
|         } | ||||
| 
 | ||||
|         // Sends the login to userLogic | ||||
|         [HttpPost("Login")] | ||||
|         public async Task<IActionResult> Login([FromBody] Login login) | ||||
|         { | ||||
|             return await _userLogic.Login(login); | ||||
|         } | ||||
| 
 | ||||
|         // Sends the user to userLogic | ||||
|         [HttpPost("Create")] | ||||
|         public async Task<IActionResult> CreateUser([FromBody] User user) | ||||
|         { | ||||
|             return await _userLogic.RegisterUser(user); | ||||
|         } | ||||
| 
 | ||||
|         // Sends the user and userId to userLogic | ||||
|         [Authorize] | ||||
|         [HttpPut("Edit/{userId}")] | ||||
|         public async Task<IActionResult> EditUser([FromBody] User user, int userId) | ||||
| @ -40,6 +43,7 @@ namespace Api.Controllers | ||||
|             return await _userLogic.EditProfile(user, userId); | ||||
|         } | ||||
| 
 | ||||
|         // Sends the userId to userLogic | ||||
|         [Authorize] | ||||
|         [HttpDelete("Delete/{userId}")] | ||||
|         public async Task<IActionResult> DeleteUser(int userId) | ||||
|  | ||||
| @ -22,7 +22,7 @@ namespace Api.DBAccess | ||||
|         /// Creates a user using entityframework core | ||||
|         /// </summary> | ||||
|         /// <param name="user">Need the entire user obj</param> | ||||
|         /// <returns>returns the true in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns> | ||||
|         /// <returns>returns true in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns> | ||||
|         public async Task<IActionResult> CreateUser(User user) | ||||
|         { | ||||
|             var users = await _context.Users.ToListAsync(); | ||||
| @ -118,7 +118,7 @@ namespace Api.DBAccess | ||||
|         /// Deletes a user from the database | ||||
|         /// </summary> | ||||
|         /// <param name="userId">The Id of the user that is to be deleted</param> | ||||
|         /// <returns>returns the true in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns> | ||||
|         /// <returns>returns true in a OkObjectResult and if there is some error it returns a ConflictObjectResult and a message that explain the reason</returns> | ||||
|         public async Task<IActionResult> DeleteUser(int userId) | ||||
|         { | ||||
|             var user = await _context.Users.Include(u => u.Devices).FirstOrDefaultAsync(u => u.Id == userId); | ||||
| @ -189,6 +189,12 @@ namespace Api.DBAccess | ||||
|             return _context.Devices.FirstOrDefault(d => d.ReferenceId == refenreId); | ||||
|         } | ||||
| 
 | ||||
|         // Returns all devices | ||||
|         public List<Device> ReadDevices() | ||||
|         { | ||||
|             return _context.Devices.ToList(); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Updates a device in the database | ||||
|         /// </summary> | ||||
|  | ||||
| @ -43,7 +43,7 @@ namespace Api.MQTTReciever | ||||
| 
 | ||||
|                     string sensorData = Encoding.UTF8.GetString(e.ApplicationMessage.Payload); | ||||
| 
 | ||||
|                     var messageReceive = JsonSerializer.Deserialize<MQTTMessageReceive>(sensorData); | ||||
|                     var messageReceive = JsonSerializer.Deserialize<MessageReceive>(sensorData); | ||||
| 
 | ||||
|                     // Checks if the message has the data we need | ||||
|                     if (messageReceive == null || messageReceive.device_id == null || messageReceive.timestamp == 0) | ||||
|  | ||||
							
								
								
									
										11
									
								
								backend/Api/Models/DeviceLimit.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								backend/Api/Models/DeviceLimit.cs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| namespace Api.Models | ||||
| { | ||||
|     public class DeviceLimit | ||||
|     { | ||||
|         public double TempHigh { get; set; } | ||||
| 
 | ||||
|         public double TempLow { get; set; } | ||||
| 
 | ||||
|         public string? ReferenceId { get; set; } | ||||
|     } | ||||
| } | ||||
| @ -1,6 +1,6 @@ | ||||
| namespace Api.Models | ||||
| { | ||||
|     public class MQTTMessageReceive | ||||
|     public class MessageReceive | ||||
|     { | ||||
|         public double temperature { get; set; } | ||||
| 
 | ||||
| @ -1,4 +1,5 @@ | ||||
| using Api; | ||||
| using Api.AMQP; | ||||
| using Api.AMQPReciever; | ||||
| using Api.DBAccess; | ||||
| using Api.MQTTReciever; | ||||
| @ -27,8 +28,10 @@ class Program | ||||
|                 // Choose to either connect AMQP or MQTT | ||||
|                 if (rabbitMQ == "AMQP") | ||||
|                 { | ||||
|                     AMQPReciever amqp = new AMQPReciever(configuration, dbAccess); | ||||
|                     amqp.Handle_Received_Application_Message().Wait(); | ||||
|                     AMQPReciever amqpReciever = new AMQPReciever(configuration, dbAccess); | ||||
|                     amqpReciever.Handle_Received_Application_Message().Wait(); | ||||
|                     AMQPPublisher aMQPPush = new AMQPPublisher(configuration, dbAccess); | ||||
|                     aMQPPush.Handle_Push_Device_Limits().Wait(); | ||||
|                 } | ||||
|                 else if (rabbitMQ == "MQTT") | ||||
|                 { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user