Dělám poprvé aplikaci s autorizací a mám trochu problém. Jsem pomocí úhlové + asp.net default auth, můj rámci dědictví, vypadá takto:
public class CoffeeContext : IdentityDbContext<User, UserRole, int>
UserRole je prázdná třída, která dědictví z IdentityRole < int >. Uživatel je také prázdná třída, která dědictví z IdentityUser < int >.
To je, jak můj UsersControllerClass vypadá:
[ApiController]
[Route("users")]
public class UsersController : ControllerBase
{
private readonly SignInManager<User> _signInManager;
private readonly UserManager<User> _userManager;
public UsersController(SignInManager<User> signInManager, UserManager<User> userManager)
{
_signInManager = signInManager;
_userManager = userManager;
}
[HttpPost]
[Route("Login")]
public async Task<IActionResult> Login(UserDto userDto)
{
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(userDto.Email, userDto.Password, false, false);
if (result.Succeeded)
{
return Ok();
}
else
{
return BadRequest();
}
}
return Ok();
}
[HttpPost]
[Route("Register")]
public async Task<IActionResult> Register(UserDto userDto)
{
if (ModelState.IsValid)
{
var user = new User() {UserName = userDto.Email, Email = userDto.Email};
var result = await _userManager.CreateAsync(user, userDto.Password);
if (result.Succeeded)
{
return Ok();
}
}
return BadRequest();
}
[HttpGet]
[Route("Logout")]
public async Task<IActionResult> Logout()
{
if (ModelState.IsValid)
{
await _signInManager.SignOutAsync();
}
return Ok();
}
}
UserDto má 2 vlastnosti: string Email, string Heslo. Mám několik tříd, které mají id uživatele vlastnost. Například recept:
[ApiController]
[Route("Recipes")]
public class RecipesController : ControllerBase
{
private readonly IRecipeService _recipeService;
private readonly Microsoft.AspNetCore.Identity.UserManager<User> _userManager;
public RecipesController(IRecipeService recipeService, Microsoft.AspNetCore.Identity.UserManager<User> userManager)
{
_recipeService = recipeService;
_userManager = userManager;
}
[HttpPost]
public async Task<IActionResult> CreateRecipe(RecipeDto recipeDto)
{
var userId = IdentityExtensions.GetUserId(User.Identity);
recipeDto.UserId = int.Parse(userId);
await _recipeService.CreateRecipe(recipeDto);
return CreatedAtAction(nameof(GetRecipeById), new { Id = recipeDto.Id }, recipeDto);
}
Jak můžete vidět jsem stále userId tím, IdentityExtension.GetUserId();
Když jsem testování této metody s swagger (první přihlášení pomocí metody od uživatele správce a pak CreateRecipe) vše funguje v pořádku, to dostane přímo id aktuálně přihlášení uživatele. Problém je, že když zkusím použít tu metodu přes frontend s úhlovou. To je, jak moje přihlašovací modul vypadá takto:
export class LoginComponent implements OnInit {
userForm! : FormGroup;
user! : LoginModel;
subbmited = false;
constructor(private formBuilder: FormBuilder, private userService: UserService) { }
ngOnInit(){
this.userForm = this.formBuilder.group({
email: ['', Validators.required],
password: ['', Validators.required]
})
}
get Email(){
return this.userForm.get('email');
}
get Password(){
return this.userForm.get('password');
}
onSubmit(){
this.user = this.userForm.value;
this.userService.LogIn(this.user).subscribe(res => { console.log(res)});
}
userService, hodnoty prošel loginComponent jsou správné (registr metoda je v pořádku):
export class UserService {
readonly ApiUrl = "https://localhost:44331/users"
constructor(private http: HttpClient) { }
LogIn(loginModel: LoginModel){
return this.http.post(this.ApiUrl + '/Login', loginModel, this.generateHeaders());
}
Register(loginModel: RegisterModel){
return this.http.post(this.ApiUrl + '/Register', loginModel, this.generateHeaders());
}
private generateHeaders = () => {
return {
headers: new HttpHeaders({
"Content-Type": "application/json",
}),
};
};
}
A to je, jak jsem přidat recept:
addRecipe(){
var val = {
id:this.RecipeId,
name:this.RecipeName,
recipeBody:this.RecipeBody,
userId: 0,
intendedUse:this.RecipeIntentedUse,
coffeeId:this.RecipeCoffeeId
};
this.service.createRecipe(val).subscribe(res=>{
alert(res.toString());
});
}
Hodnoty ze vstupů jsou správné, a jsem si nastavit userId na 0, protože to bude nahrazen v každém případě v backend (nebo alespoň myslím, že by mělo). Nakonec dostávám Http status: 500, Hodnota nemůže být null. Když jsem zkontrolovat s debbuging jak userId hodnota vypadá v backend:
Jak můžete vidět aktuálně přihlášeného uživatele Id null, což předpokládám znamená, že neexistuje žádný přihlášení uživatelé. Jak to mohu opravit?
Edit: recept.komponenta.ts:
import { Component, OnInit } from '@angular/core';
import { SharedService } from '../shared/shared.service';
@Component({
selector: 'app-recipe',
templateUrl: './recipe.component.html',
styleUrls: ['./recipe.component.css']
})
export class RecipeComponent implements OnInit {
ModalTitle:string="";
recipe: any;
ActiveAddEdditRecipe:boolean=false;
constructor(private service:SharedService) { }
RecipeList: any = [];
ngOnInit(): void {
this.refreshRecipeList();
}
refreshRecipeList(){
this.service.getRecipes().subscribe(data => {
this.RecipeList=data;
})
}
addClick(){
this.recipe={
id:0,
name:"",
recipeBody:"",
userId:"",
intendedUse:"",
coffeeId:""
}
this.ModalTitle="Add recipe";
this.ActiveAddEdditRecipe=true;
}
editClick(recipeEdit: any){
this.recipe=recipeEdit;
this.ModalTitle="Edit recipe";
this.ActiveAddEdditRecipe=true;
}
closeClick(){
this.ActiveAddEdditRecipe=false;
this.refreshRecipeList();
}
deleteClick(recipeDelete: any){
this.service.deleteRecipe(recipeDelete).subscribe(data => this.refreshRecipeList());
}
}
html:
<button type="button" class="btn btn-primary float-right m-2" data-bs-toggle="modal" data-bs-target="#exampleModal"
(click)="addClick()"
data-backdrop="static"
data-keyboard="false">
Add Coffee
</button>
<div class="modal" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">{{ModalTitle}}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"
(click)="closeClick()" (click)="refreshRecipeList()">
</button>
</div>
<div class="modal-body">
<app-add-edit-recipe [recipe]="recipe" *ngIf="ActiveAddEdditRecipe"></app-add-edit-recipe>
</div>
</div>
</div>
</div>
<div class="wrapper">
<header>
<h1>Recipe</h1>
</header>
<section class="columns" *ngFor="let recipe of RecipeList">
<div class="column">
<h2>{{recipe.name}}</h2>
<p>{{recipe.recipeBody}}</p>
</div>
</section>
</div>
A AddEditRecipeComponent
Component({
selector: 'app-add-edit-recipe',
templateUrl: './add-edit-recipe.component.html',
styleUrls: ['./add-edit-recipe.component.css']
})
export class AddEditRecipeComponent implements OnInit {
@Input() recipe: any;
RecipeId!: number ;
RecipeName: string="";
RecipeBody : string="";
RecipeUserId : number = 0;
RecipeIntentedUse: string ="";
RecipeCoffeeId: string ="";
CoffeeList: any[] = [];
constructor(private service : SharedService) { }
ngOnInit(): void {
this.RecipeId = this.recipe.id;
this.RecipeName = this.recipe.name;
this.RecipeBody = this.recipe.recipeBody;
this.RecipeUserId = this.recipe.userId;
this.RecipeIntentedUse = this.recipe.intendedUse;
this.RecipeCoffeeId = this.recipe.coffeeId;
this.getCoffeesList();
}
addRecipe(){
var val = {
id:this.RecipeId,
name:this.RecipeName,
recipeBody:this.RecipeBody,
userId: 1,
intendedUse:this.RecipeIntentedUse,
coffeeId:this.RecipeCoffeeId
};
this.service.createRecipe(val).subscribe(res=>{
alert(res.toString());
});
}
updateRecipe(){
var val = {
id:this.RecipeId,
name:this.RecipeName,
recipeBody:this.RecipeBody,
userId:this.RecipeUserId,
intendedUse:this.RecipeIntentedUse,
coffeeId:this.RecipeCoffeeId
};
this.service.updateRecipe(val).subscribe(res=>{
alert(res.toString());
});
}
getCoffeesList(){
this.service.getCoffees().subscribe(data => {
this.CoffeeList = data;
})
}
}
<div class ="col-sm-10">
<input type="text" class="form-control" [(ngModel)]="RecipeName" placeholder="Enter recipe name">
<input type="text" class="form-control" [(ngModel)]="RecipeBody" placeholder="Enter recipe text">
<select type="text" class="form-control" [(ngModel)]="RecipeIntentedUse">
<option value="" disabled selected>Intended Use</option>
<option value="Espresso">Espresso</option>
<option value="Aeropress">Aeropress</option>
<option value="FrenchPress">FrenchPress</option>
<option value="Chemex">Chemex</option>
<option value="Dripper">MediDripperum</option>
<option value="MokaPot">MokaPot</option>
</select>
<select type="text" class="form-control" [(ngModel)]="RecipeCoffeeId">
<option value="" disabled selected>Select coffee</option>
<option *ngFor="let coffee of CoffeeList"
[value]="coffee.id" >{{coffee.name}}</option>
</select>
</div>
Přidat
Aktualizace