/** * Login de utilizadores já existentes. Devem ser recebidos o username e password. * Sempre que o login é feito com sucesso, é enviado um ID de sessão único para o cliente * que é usado por este para se identificar sempre que envia algum pedido. */ public async override Task <UserLoginModel> Login(UserLoginLookupModel request, ServerCallContext context) { UserLoginModel output = new UserLoginModel(); // Transformação de todos os carateres do nome para upper case string username = request.Username;//.ToUpper(); // Encriptação da password SHA512 sha512 = SHA512Managed.Create(); byte[] bytes = sha512.ComputeHash(Encoding.UTF8.GetBytes(request.Password)); string password = Convert.ToBase64String(bytes); // Verifica-se se o utilizador existe na base de dados e se a password está correta Models.User u = _context.User.FirstOrDefault(u => u.Username == request.Username && u.Password == password); if (u == null) { // Se não existir nenhuma entrada na base de dados com o username e password igual, então o output tem de ser autenticação inválida. output.Valid = false; output.SessionID = ""; } else { // Sempre que um utilizador se autentica, é gerado sempre um novo ID de sessão. // É usado um ciclo para, no caso do ID de sessão gerado já existir, poder gerar um novo bool success; do { success = true; try { u.GenerateSessionID(); _context.SaveChanges(); // Altera o id de sessão do cliente, na base de dados da API. await APIServerCommunication.UserLogin(u.SessionID, u.Id); } // Exceção que é lançada sempre que é quebrado o constraint UNIQUE do ID de sessão, no caso do ID de sessão gerado já existir catch (DbUpdateException e) when(e.InnerException is SqlException sqlEx && (sqlEx.Number == 2627 || sqlEx.Number == 2601)) { success = false; } }while (success == false); // Se o login for feito com sucesso, é enviada uma confirmação ao cliente, com o seu ID de sessão output.Valid = true; output.SessionID = u.SessionID; } return(await Task.FromResult(output)); }