Esta todo a medio hacerse pero quiero versionar esto ya para no perder

nada
This commit is contained in:
2025-05-08 01:00:34 -03:00
parent 6f6d8a4e8c
commit 02add8907e
11 changed files with 348 additions and 58 deletions

View File

@@ -54,4 +54,14 @@ public class UsuarioController : ControllerBase
return ret ? Ok(new { message = "Email de recuperación actualizado con éxito" }) : BadRequest(new { message = "No se pudo actualizar el email de recuperación" });
}
public record recuperarusuario(string Email, string EmailRecuperacion);
[HttpPost("/api/recuperarUsuario")]
public IActionResult RecuperarUsuario([FromBody] recuperarusuario mails)
{
bool check = RepositorioUsuarios.Singleton.CheckEmailRecuperacion(mails.Email, mails.EmailRecuperacion);
if (check == false) return BadRequest(new { message = "El email no corresponde al email de recuperacion" });
//WIP hacer emailer
}
}

View File

@@ -0,0 +1,28 @@
using System.Net.Mail;
namespace AlquilaFacil.Emailer.Builder;
public class EmailBuilder
{
private MailMessage _message = new();
public EmailBuilder To(string to)
{
_message.To.Add(to);
return this;
}
public EmailBuilder Subject(string subject)
{
_message.Subject = subject;
return this;
}
public EmailBuilder Body(string email, string pin)
{
_message.IsBodyHtml = true;
_message.Body = new HtmlGenerator().GenerarMail2fa(email, pin);
return this;
}
public MailMessage Build() => _message;
}

View File

@@ -0,0 +1,58 @@
namespace AlquilaFacil.Emailer.Builder;
public class HtmlGenerator
{
public string GenerarMail2fa(string emailUsuario, string pin)
{
var msg = $"""
<!doctype html>
<html>
<body>
<div
style='background-color:#000000;color:#FFFFFF;font-family:"Iowan Old Style", "Palatino Linotype", "URW Palladio L", P052, serif;font-size:16px;font-weight:400;letter-spacing:0.15008px;line-height:1.5;margin:0;padding:32px 0;min-height:100%;width:100%'
>
<table
align="center"
width="100%"
style="margin:0 auto;max-width:600px;background-color:#000000"
role="presentation"
cellspacing="0"
cellpadding="0"
border="0"
>
<tbody>
<tr style="width:100%">
<td>
<div
style="color:#ffffff;font-size:16px;font-weight:normal;text-align:center;padding:16px 24px 16px 24px"
>
Aqui esta su codigo OTP:
</div>
<h1
style='font-weight:bold;text-align:center;margin:0;font-family:"Nimbus Mono PS", "Courier New", "Cutive Mono", monospace;font-size:32px;padding:16px 24px 16px 24px'
>
{pin}
</h1>
<div
style="color:#868686;font-size:16px;font-weight:normal;text-align:center;padding:16px 24px 16px 24px"
>
Este codigo es del usuario con email:{emailUsuario}
</div>
<div
style="color:#868686;font-size:14px;font-weight:normal;text-align:center;padding:16px 24px 16px 24px"
>
Si no sabes para que es el email, ignoralo.
</div>
</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
""";
return msg;
}
}

View File

@@ -0,0 +1,9 @@
using System.Net.Mail;
namespace AlquilaFacil.Emailer.Sender;
public interface IEmailSender
{
public void Send(MailMessage message, SmtpClient smtp);
}

View File

@@ -0,0 +1,25 @@
namespace AlquilaFacil.Emailer.Sender;
using System.Net.Mail;
public class OtpEmailSender : IEmailSender
{
private readonly int _codigoLength;
public OtpEmailSenderDecorator(int codigoLength = 6)
{
_codigoLength = codigoLength;
}
public void Send(MailMessage message, SmtpClient? smtp = null)
{
if (smtp == null)
{
smtp = new();
//WIP
smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
}
// 4.2 Construir HTML de verificación
}

View File

@@ -1,5 +1,9 @@
{
"usr": "nwFNMLJcn5m0owbzeXMs",
"scrt": "Mf9HxTir5mIGwWSBtQXd6DRK2k00V0EyXk7QTu70",
"connectiondb": "Server=127.0.0.1;Port=3306;Database=AlquilaFacil;Uid=AlquilaFacil;Pwd=.n@9c2ve*0,b1ETv].Kipa/~pR~V;Connection Timeout=5;SslMode=none"
"connectiondb": "Server=127.0.0.1;Port=3306;Database=AlquilaFacil;Uid=AlquilaFacil;Pwd=.n@9c2ve*0,b1ETv].Kipa/~pR~V;Connection Timeout=5;SslMode=none",
"smtpHost": "smtp.gmail.com",
"smtpPort": "587",
"emailAddr": "emailerpasillo@gmail.com",
"emailPass": "hgwa mznx xuff exws"
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
namespace Entidades;
public partial class EstadoPropiedad
{
public int Id { get; set; }
public string Descripcion { get; set; } = null!;
public virtual ICollection<Propiedade> Propiedades { get; set; } = new List<Propiedade>();
}

23
Entidades/LogDetalle.cs Normal file
View File

@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
namespace Entidades;
public partial class LogDetalle
{
public DateTime Fecha { get; set; }
public long Dniusuario { get; set; }
public string NombreTabla { get; set; } = null!;
public string Columna { get; set; } = null!;
public string? ValorAnterior { get; set; }
public string? ValorNuevo { get; set; }
public int Id { get; set; }
public virtual Log Log { get; set; } = null!;
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
namespace Entidades;
public partial class TipoPropiedad
{
public int Id { get; set; }
public string Descripcion { get; set; } = null!;
public virtual ICollection<Propiedade> Propiedades { get; set; } = new List<Propiedade>();
}

View File

@@ -1,11 +1,23 @@
<script>
import { CardHeader, CardTitle, Button, Card, Input, Form, CardBody, FormGroup } from '@sveltestrap/sveltestrap';
import { navigate } from 'svelte-routing';
import {
CardHeader,
CardTitle,
Button,
Card,
Input,
Form,
CardBody,
FormGroup,
Modal,
} from "@sveltestrap/sveltestrap";
import { navigate } from "svelte-routing";
import { urlG } from "../stores/urlStore";
import ModalEstatico from "./ModalEstatico.svelte";
import { parse } from "svelte/compiler";
let email = $state("")
let contraseña = $state("")
let errorMessage = $state("")
let email = $state("");
let contraseña = $state("");
let errorMessage = $state("");
// @ts-ignore
async function submitForm(event) {
@@ -14,53 +26,136 @@
const data = { email, contraseña };
try {
const response = await fetch(String($urlG) + "/api/login", {
method: 'POST',
method: "POST",
headers: {
'Content-Type': 'application/json'
"Content-Type": "application/json",
},
body: JSON.stringify(data),
credentials: "include"
credentials: "include",
});
if (!response.ok) {
const errorData = await response.json()
const errorData = await response.json();
errorMessage = errorData.message;
return;
}
const ret = await response.json();
localStorage.setItem('email', ret.email);
sessionStorage.setItem('token', ret.token);
localStorage.setItem("email", ret.email);
sessionStorage.setItem("token", ret.token);
//setTimeout(() => console.log("50ms") ,50);
navigate(ret.redirect);
} catch (e) {
} catch (e) {}
}
let showrecuperarmodal = $state(false);
let modaldata = $state("");
async function SubmitRecuperarContraseñaEmail(e) {
e.preventDefault();
return;
try {
const req = await fetch($urlG + "");
} catch {
modaldata = "Fallo al hacer la request";
}
} //WIP
</script>
<Card class="position-sticky top-50 start-50 translate-middle-x border border-success" style="width: 20rem; height: auto;" theme="auto" outline>
{#if modaldata}
<ModalEstatico close={() => !!(modaldata = "")} payload={modaldata} />
{/if}
<Card
class="position-sticky top-50 start-50 translate-middle-x border border-success"
style="width: 20rem; height: auto;"
theme="auto"
outline
>
<CardHeader>
<CardTitle>Iniciar Sesión</CardTitle>
</CardHeader>
<CardBody>
<Form on:submit={submitForm}>
<Form onsubmit={(e) => submitForm(e)}>
<FormGroup floating label="Email">
<Input type="email" placeholder="ejemplo@mail.com" bind:value={email} required/>
<Input
type="email"
placeholder="ejemplo@mail.com"
bind:value={email}
required
/>
</FormGroup>
<FormGroup floating label="Contraseña">
<Input type="password" placeholder="*********" bind:value={contraseña} required/>
<Input
type="password"
placeholder="*********"
bind:value={contraseña}
required
/>
</FormGroup>
<FormGroup>
<Button color="primary" type="submit">Ingresar</Button>
</FormGroup>
</Form>
{#if errorMessage}
<div class='alert alert-warning alert-dismissible fade show' role='alert'>
<div
class="alert alert-warning alert-dismissible fade show"
role="alert"
>
<strong>{errorMessage}</strong>
<button type="button" class="btn-close close" aria-label="Close" data-bs-dismiss="alert"></button>
<button
type="button"
class="btn-close close"
aria-label="Close"
data-bs-dismiss="alert"
></button>
</div>
{/if}
<hr />
<a href="#" onclick={() => (showrecuperarmodal = true)}
>Recuperar Contraseña</a
>
</CardBody>
</Card>
{#if showrecuperarmodal}
<div
class="modal"
tabindex="-1"
style="display: block; background-color: rgba(0, 0, 0, 0.3);"
>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Recuperar Contraseña</h5>
<button
type="button"
class="btn-close"
aria-label="Close"
onclick={() => (showrecuperarmodal = false)}
></button>
</div>
<div class="modal-body">
<form onsubmit={SubmitRecuperarContraseñaEmail}>
<div class="mb-3">
<label for="recoveryEmail" class="form-label"
>Email</label
>
<input
type="email"
class="form-control"
id="recoveryEmail"
placeholder="Ingresa tu email"
required
/>
</div>
<div class="d-grid gap-2">
<button type="submit" class="btn btn-primary"
>Enviar</button
>
</div>
</form>
</div>
</div>
</div>
</div>
{/if}

View File

@@ -11,6 +11,18 @@ namespace Modelo;
public class RepositorioUsuarios : RepositorioBase<RepositorioUsuarios>
{
public bool CheckEmailRecuperacion(string Email, string EmailRecuperacion)
{
var con = Context;
Cliente cli = con.Clientes.FirstOrDefault(x => x.Email == Email);
if (cli == null) return false;
if (cli.EmailRecuperacion == EmailRecuperacion)
{
base.GenerarLog(con, cli.Dni, "Intento de recuperar Usuario");
return true;
}
return false;
}
public bool SetEmailRecuperacion(string emailrecuperacion, Cliente cli)
{