17 Aug 2023
|
Tutoriales
Trucos
Codigo paso a paso para conectar y enviar un topic a AWS IOT usando Node.js.
En mi canal de youtube hay un video del paso a paso:
-
Creamos un objeto en AWS y descargamos el código de ejemplo
- Creamos un proyecto node
- Agregamos archivo:
- instalamos libreria
- Ingresamos el codigo node:
const awsIot = require('aws-iot-device-sdk');
const today = new Date();
const date = today.getFullYear() + '-' + (today.getMonth() + 1) + '-' + today.getDate();
const time = today.getHours() + ":" + today.getMinutes() + ":" + today.getSeconds();
const dateTime = date + ' ' + time;
const topic = "topic"
const device = awsIot.device({
clientId: 'clientId',
host: 'host',
port: 8883,
keyPath: './private.key',
certPath: './cert.pem',
caPath: './CA.crt',
});
const IoTDevice = {
serialNumber: "SN-D7F3C8947867",
dateTime,
activated: true,
device: "MyRaspperry-01",
type: "MySmartIoTDevice",
payload: {}
}
const getSensorData = (cb) => getDummySensorData(cb);
const getDummySensorData = (cb) => {
const temperatureData = { temp: '100°C', humidity: '52%' }
return cb(temperatureData)
}
const sendData = (data) => {
const telemetryData = {
...IoTDevice,
payload: data
}
console.log(`STEP - Sending data to AWS IoT Core'`, telemetryData)
console.log(`---------------------------------------------------------------------------------`)
return device.publish(topic, JSON.stringify(telemetryData))
}
device
.on('connect', function () {
console.log('STEP - Connecting to AWS IoT Core');
console.log(`---------------------------------------------------------------------------------`)
setInterval(() => getSensorData(sendData), 3000)
});
device
.on('message', function (topic, payload) {
console.log('message', topic, payload.toString());
});
device
.on('error', function (topic, payload) {
console.log('Error:', topic, payload.toString());
});
30 Jul 2023
|
Tutoriales
Trucos
Codigo paso a paso para integrar Clean Arquitecture a Net Core 7.
En mi canal de youtube hay un video del paso a paso:
-
Creamos una Blank Solution
- Agregamos proyecto API .Api
- Agregamos proyecto Class Library .Core
- DTOs
- Entities
- Enumerations
- Interfaces
- Exceptions
- QueryFilters
- Services
- Agregamos proyecto Class Library .Infrastructure
- Data
- Repositories
- Filters
- Mappings
- Validators
- Reference
- .API = .Core, .Infrastructure
- .Infrastructure = .Core
- Ingresamos al appsettings:
,
"MongoDbSettings": {
"ConnectionString": "url",
"DatabaseName": "namestring"
}
- Creamos MongoDbSettingsEntity:
public string ConnectionString { get; set; } = string.Empty;
public string DatabaseName { get; set; } = string.Empty;
- Instalamos paquetes:
MongoDB.Bson
MongoDB.Driver
Microsoft.Extensions.Options
AspNetCore.Identity.MongoDbCore
- Agregamos al program:
builder.Services.Configure<MongoDbSettingsEntity>(builder.Configuration.GetSection(nameof(MongoDbSettings)));
- Creamos el UserEntity:
[BsonIgnoreExtraElements]
public class UserEntity
{
[BsonId]
[BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]
public string Id { get; set; } = string.Empty;
public string Username { get; set; } = string.Empty;
public string Fullmane { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
}
- Creamos IUserRepository y IUserService:
Task<List<UserEntity>> GetAll();
- Creamos IContext:
IMongoCollection<UserEntity> Users { get; }
- Creamos Context:
public class Context : IContext
{
private readonly IMongoDatabase _database;
public Context(IOptions<MongoDbSettingsEntity> options)
{
MongoClient _mongoClient = new MongoClient(options.Value.ConnectionString);
_database = _mongoClient.GetDatabase(options.Value.DatabaseName);
}
public IMongoCollection<UserEntity> Users => _database.GetCollection<UserEntity>("users");
}
- Creamos UserRepository:
public class UserRepository : IUserRepository
{
private readonly IContext _context;
public UserRepository(IContext context)
{
_context = context;
}
public async Task<List<UserEntity>> GetAll() => await _context.Users.Find(_ => true).ToListAsync();
}
- Creamos UserService:
public class UserService : IUserService
{
private readonly IUserRepository _userRepository;
public UserService(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public Task<List<UserEntity>> GetAll()
{
return _userRepository.GetAll();
}
}
- Creamos UserService:
public class UserService : IUserService
{
private readonly IUserRepository _userRepository;
public UserService(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public Task<List<UserEntity>> GetAll()
{
return _userRepository.GetAll();
}
}
- Agregamos al program:
builder.Services.AddSingleton<IUserService, UserService>();
builder.Services.AddSingleton<IUserRepository, UserRepository>();
- Creo UserController:
[Route("api/[controller]")]
[ApiController]
public class UserController : ControllerBase
{
private readonly IUserService _userService;
public UserController(IUserService userService)
{
_userService = userService;
}
// GET: api/<UserController>
[HttpGet]
public async Task<List<UserEntity>> GetAll()
{
return await _userService.GetAll();
}
}
29 Jul 2023
|
Tutoriales
Trucos
Codigo paso a paso para integrar EntityUser y JWT con MongoDB.
En mi canal de youtube hay un video del paso a paso:
Instalamos paquetes:
AspNetCore.Identity.MongoDbCore
MongoDB.Bson
MongoDB.Driver
Microsoft.AspNetCore.Authentication.JwtBearer
Ingresamos al appsettings:
,
"MongoDbSettings": {
"ConnectionString": "url",
"DatabaseName": "namestring"
}
Creamos ApplicationUser:
[CollectionName("users")]
public class ApplicationUser : MongoIdentityUser<Guid>
{
public string FullName { get; set; } = string.Empty;
}
Creamos ApplicationRole:
[CollectionName("roles")]
public class ApplicationRole : MongoIdentityRole<Guid>
{
}
Agregamos a Program.cs:
// Add services to the container.
builder.Services.Configure<MongoDbSettings>(builder.Configuration.GetSection(nameof(MongoDbSettings)));
BsonSerializer.RegisterSerializer(new GuidSerializer(MongoDB.Bson.BsonType.String));
BsonSerializer.RegisterSerializer(new DateTimeSerializer(MongoDB.Bson.BsonType.String));
BsonSerializer.RegisterSerializer(new DateTimeOffsetSerializer(MongoDB.Bson.BsonType.String));
//add mongoIdentityConfiguration...
var mongoDbIdentityConfig = new MongoDbIdentityConfiguration
{
MongoDbSettings = builder.Configuration.GetSection(nameof(MongoDbSettings)).Get<MongoDbSettings>(),
IdentityOptionsAction = options =>
{
options.Password.RequireDigit = false;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireLowercase = false;
//lockout
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(10);
options.Lockout.MaxFailedAccessAttempts = 5;
options.User.RequireUniqueEmail = true;
}
};
builder.Services.ConfigureMongoDbIdentity<ApplicationUser, ApplicationRole, Guid>(mongoDbIdentityConfig)
.AddUserManager<UserManager<ApplicationUser>>()
.AddSignInManager<SignInManager<ApplicationUser>>()
.AddRoleManager<RoleManager<ApplicationRole>>()
.AddDefaultTokenProviders();
builder.Services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =>
{
x.RequireHttpsMetadata = true;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidIssuer = "https://localhost:5001",
ValidAudience = "https://localhost:5001",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("1swek3u4uo2u4a6e")),
ClockSkew = TimeSpan.Zero
};
});
builder.Services.AddSwaggerGen(setup =>
{
// Include 'SecurityScheme' to use JWT Authentication
var jwtSecurityScheme = new OpenApiSecurityScheme
{
BearerFormat = "JWT",
Name = "JWT Authentication",
In = ParameterLocation.Header,
Type = SecuritySchemeType.Http,
Scheme = JwtBearerDefaults.AuthenticationScheme,
Description = "Put **_ONLY_** your JWT Bearer token on textbox below!",
Reference = new OpenApiReference
{
Id = JwtBearerDefaults.AuthenticationScheme,
Type = ReferenceType.SecurityScheme
}
};
setup.AddSecurityDefinition(jwtSecurityScheme.Reference.Id, jwtSecurityScheme);
setup.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{ jwtSecurityScheme, Array.Empty<string>() }
});
});
Creamos LoginRequest Dto:
[Required, EmailAddress]
public string Email { get; set; } = string.Empty;
[Required, DataType(DataType.Password)]
public string Password { get; set; } = string.Empty;
Creamos RegisterRequest Dto:
[Required, EmailAddress]
public string Email { get; set; } = string.Empty;
public string Username { get; set; } = string.Empty;
[Required]
public string FullName { get; set; } = string.Empty;
[Required, DataType(DataType.Password)]
public string Password { get; set; } = string.Empty;
[Required, DataType(DataType.Password), Compare(nameof(Password), ErrorMessage = "Passwords do not match")]
public string ConfirmPassword { get; set; } = string.Empty;
Creamos CreateRoleRequest Dto:
public string Role { get; set; } = string.Empty;
Creamos LoginResponse Dto:
public bool Success { get; set; }
public string AccessToken { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty;
public string UserId { get; set; } = string.Empty;
public string Message { get; set; } = string.Empty;
Creamos RegisterResponse Dto:
public string Message { get; set; } = string.Empty;
public bool Success { get; set; }
Creamos AuthenticationController:
[ApiController]
[Route("api/v1/authenticate")]
public class AuthenticationController : ControllerBase
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly RoleManager<ApplicationRole> _roleManager;
public AuthenticationController(UserManager<ApplicationUser> userManager, RoleManager<ApplicationRole> roleManager)
{
_userManager = userManager;
_roleManager = roleManager;
}
[HttpPost]
[Route("roles/add")]
public async Task<IActionResult> CreateRole([FromBody] CreateRoleRequest request)
{
var appRole = new ApplicationRole { Name = request.Role };
var createRole = await _roleManager.CreateAsync(appRole);
return Ok(new { message = "role created succesfully" });
}
[HttpPost]
[Route("register")]
public async Task<IActionResult> Register([FromBody] RegisterRequest request)
{
var result = await RegisterAsync(request);
return result.Success ? Ok(result) : BadRequest(result.Message);
}
private async Task<RegisterResponse> RegisterAsync(RegisterRequest request)
{
try
{
var userExists = await _userManager.FindByEmailAsync(request.Email);
if(userExists != null) return new RegisterResponse { Message = "User already exists", Success = false };
//if we get here, no user with this email..
userExists = new ApplicationUser
{
FullName = request.FullName,
Email = request.Email,
ConcurrencyStamp = Guid.NewGuid().ToString(),
UserName = request.Email,
};
var createUserResult = await _userManager.CreateAsync(userExists, request.Password);
if(!createUserResult.Succeeded) return new RegisterResponse { Message = $"Create user failed {createUserResult?.Errors?.First()?.Description}", Success = false };
//user is created...
//then add user to a role...
var addUserToRoleResult = await _userManager.AddToRoleAsync(userExists, "USER");
if(!addUserToRoleResult.Succeeded) return new RegisterResponse { Message = $"Create user succeeded but could not add user to role {addUserToRoleResult?.Errors?.First()?.Description}", Success = false };
//all is still well..
return new RegisterResponse
{
Success = true,
Message = "User registered successfully"
};
}
catch (Exception ex)
{
return new RegisterResponse { Message = ex.Message, Success = false };
}
}
[HttpPost]
[Route("login")]
[ProducesResponseType((int) HttpStatusCode.OK , Type = typeof(LoginResponse))]
public async Task<IActionResult> Login([FromBody] LoginRequest request)
{
var result = await LoginAsync(request);
return result.Success ? Ok(result) : BadRequest(result.Message);
}
private async Task<LoginResponse> LoginAsync(LoginRequest request)
{
try
{
var user = await _userManager.FindByEmailAsync(request.Email);
if (user is null) return new LoginResponse { Message = "Invalid email/password", Success = false };
//all is well if ew reach here
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()),
new Claim(ClaimTypes.Name, user.UserName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString())
};
var roles = await _userManager.GetRolesAsync(user);
var roleClaims = roles.Select(x => new Claim(ClaimTypes.Role, x));
claims.AddRange(roleClaims);
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("1swek3u4uo2u4a6e"));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var expires = DateTime.Now.AddMinutes(30);
var token = new JwtSecurityToken(
issuer: "https://localhost:5001",
audience: "https://localhost:5001",
claims: claims,
expires: expires,
signingCredentials: creds
);
return new LoginResponse
{
AccessToken = new JwtSecurityTokenHandler().WriteToken(token),
Message = "Login Successful",
Email = user?.Email,
Success = true,
UserId = user?.Id.ToString()
};
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return new LoginResponse { Success = false, Message = ex.Message };
}
}
}
Agregamos [Authorize]
03 Feb 2023
|
Tutoriales
Trucos
Codigo para agregar un contador de balas en Roblox Studio usando el (ACS) Advanced Combat System.
En mi canal de youtube hay un video del paso a paso:
Editar linea 1511 en StarterPlayer/StarterCharacterScripts/ACS_Client/ACS_Framework
if WeaponData.ShootType == 1 then
HUD.FText.Text = Ammo.."/"..StoredAmmo.." | Semi"
elseif WeaponData.ShootType == 2 then
HUD.FText.Text = Ammo.."/"..StoredAmmo.." | Burst"
elseif WeaponData.ShootType == 3 then
HUD.FText.Text = Ammo.."/"..StoredAmmo.." | Auto"
elseif WeaponData.ShootType == 4 then
HUD.FText.Text = Ammo.."/"..StoredAmmo.." | Pump-Action"
elseif WeaponData.ShootType == 5 then
HUD.FText.Text = Ammo.."/"..StoredAmmo.." | Bolt-Action"
end
21 Jan 2023
|
Tutoriales
Trucos
Paso a paso para crear una prueba unitaria basica con Jest en React con Vite y Typescript.
En mi canal de youtube hay un video del paso a paso:
yarn add --dev jest babel-jest @babel/preset-env @babel/preset-react
yarn add --dev @testing-library/react @testing-library/dom @testing-library/user-event @types/jest jest-environment-jsdom
yarn add --dev jest-svg-transformer
pnpm i --save-dev @babel/core @babel/preset-typescript
pnpm i --save-dev identity-obj-proxy
"test": "jest --watchAll=false --coverage --CI=true"
babel.config.js
module.exports = {
presets: [
[ '@babel/preset-env', { targets: { esmodules: true } } ],
[ '@babel/preset-react', { runtime: 'automatic' } ],
'@babel/preset-typescript',
],
};
jest.config.js
module.exports = {
testEnvironment: 'jest-environment-jsdom',
setupFiles: ['./jest.setup.js'],
moduleNameMapper: {
"^.+\\.svg$": "jest-svg-transformer",
"\\.(css|less|scss)$": "identity-obj-proxy",
}
}
jest.setup.js
App.test.tsx
import { render, screen } from '@testing-library/react';
import App from '../App';
test('Renders main page correctly', async () => {
render(<App />);
const buttonCount = await screen.findByRole('button');
expect(buttonCount.innerHTML).toBe('count is 0');
expect(true).toBeTruthy();
});