Skip to content

Commit 42c734f

Browse files
committed
update service
1 parent 6464b24 commit 42c734f

File tree

3 files changed

+434
-195
lines changed

3 files changed

+434
-195
lines changed

3-Authorization-II/1-call-api/API/TodoListAPI/Controllers/TodoListController.cs

Lines changed: 236 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -11,142 +11,268 @@
1111
using Microsoft.Identity.Web;
1212
using Microsoft.Identity.Web.Resource;
1313

14+
15+
16+
// using Microsoft.AspNetCore.Authorization;
17+
// using Microsoft.AspNetCore.Http;
18+
// using Microsoft.AspNetCore.Mvc;
19+
// using Microsoft.Identity.Web;
20+
// using Microsoft.Identity.Web.Resource;
21+
// using System;
22+
// using System.Collections.Generic;
23+
// using System.Linq;
24+
// using System.Security.Claims;
25+
// using TodoListClient.Models;
26+
1427
namespace TodoListAPI.Controllers
1528
{
16-
[Authorize]
17-
[Route("api/[controller]")]
18-
[ApiController]
19-
public class TodoListController : ControllerBase
29+
[Authorize]
30+
[Route("api/[controller]")]
31+
[ApiController]
32+
public class TodoListController : ControllerBase
33+
{
34+
// The Web API will only accept tokens 1) for users, and
35+
// 2) having the access_as_user scope for this API
36+
static readonly string[] scopeRequiredByApi = new string[] { "access_as_user" };
37+
38+
private readonly TodoContext _context;
39+
40+
public TodoListController(TodoContext context)
41+
{
42+
_context = context;
43+
}
44+
45+
// GET: api/TodoItems
46+
[HttpGet]
47+
public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems()
48+
{
49+
HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);
50+
string owner = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
51+
return await _context.TodoItems.Where(item => item.Owner == owner).ToListAsync();
52+
}
53+
54+
// [HttpGet]
55+
// [RequiredScopeOrAppPermission(
56+
// AcceptedScope = new string[] { "ToDoList.Read", "ToDoList.ReadWrite" },
57+
// AcceptedAppPermission = new string[] { "ToDoList.Read.All", "ToDoList.ReadWrite.All" }
58+
// )]
59+
// public IEnumerable<Todo> Get()
60+
// {
61+
// if (HasDelegatedPermissions(new string[] { "ToDoList.Read", "ToDoList.ReadWrite" }))
62+
// {
63+
// return TodoStore.Values.Where(x => x.Owner == HttpContext.User.GetObjectId());
64+
// }
65+
// else if (HasApplicationPermissions(new string[] { "ToDoList.Read.All", "ToDoList.ReadWrite.All" }))
66+
// {
67+
// return TodoStore.Values;
68+
// }
69+
70+
// return null;
71+
// }
72+
73+
// GET: api/TodoItems/5
74+
[HttpGet("{id}")]
75+
public async Task<ActionResult<TodoItem>> GetTodoItem(int id)
76+
{
77+
HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);
78+
79+
var todoItem = await _context.TodoItems.FindAsync(id);
80+
81+
if (todoItem == null)
82+
{
83+
return NotFound();
84+
}
85+
86+
return todoItem;
87+
}
88+
89+
// [HttpGet("{id}", Name = "Get")]
90+
// [RequiredScopeOrAppPermission(
91+
// AcceptedScope = new string[] { "ToDoList.Read", "ToDoList.ReadWrite" },
92+
// AcceptedAppPermission = new string[] { "ToDoList.Read.All", "ToDoList.ReadWrite.All" })]
93+
// public Todo Get(int id)
94+
// {
95+
// //if it only has delegated permissions
96+
// //then it will be t.id==id && x.Owner == owner
97+
// //if it has app permissions the it will return t.id==id
98+
99+
// if (HasDelegatedPermissions(new string[] { "ToDoList.Read", "ToDoList.ReadWrite" }))
100+
// {
101+
// return TodoStore.Values.FirstOrDefault(t => t.Id == id && t.Owner == _contextAccessor.HttpContext.User.GetObjectId());
102+
// }
103+
// else if (HasApplicationPermissions(new string[] { "ToDoList.Read.All", "ToDoList.ReadWrite.All" }))
104+
// {
105+
// return TodoStore.Values.FirstOrDefault(t => t.Id == id);
106+
// }
107+
108+
// return null;
109+
// }
110+
111+
// PUT: api/TodoItems/5
112+
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
113+
// more details see https://aka.ms/RazorPagesCRUD.
114+
[HttpPut("{id}")]
115+
public async Task<IActionResult> PutTodoItem(int id, TodoItem todoItem)
20116
{
21-
// The Web API will only accept tokens 1) for users, and
22-
// 2) having the access_as_user scope for this API
23-
static readonly string[] scopeRequiredByApi = new string[] { "access_as_user" };
117+
HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);
118+
119+
if (id != todoItem.Id)
120+
{
121+
return BadRequest();
122+
}
24123

25-
private readonly TodoContext _context;
124+
_context.Entry(todoItem).State = EntityState.Modified;
26125

27-
public TodoListController(TodoContext context)
126+
try
127+
{
128+
await _context.SaveChangesAsync();
129+
}
130+
catch (DbUpdateConcurrencyException)
131+
{
132+
if (!TodoItemExists(id))
28133
{
29-
_context = context;
134+
return NotFound();
30135
}
31-
32-
// GET: api/TodoItems
33-
[HttpGet]
34-
public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems()
136+
else
35137
{
36-
HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);
37-
string owner = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
38-
return await _context.TodoItems.Where(item => item.Owner == owner).ToListAsync();
138+
throw;
39139
}
140+
}
40141

41-
// GET: api/TodoItems/5
42-
[HttpGet("{id}")]
43-
public async Task<ActionResult<TodoItem>> GetTodoItem(int id)
44-
{
45-
HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);
142+
return NoContent();
143+
}
46144

47-
var todoItem = await _context.TodoItems.FindAsync(id);
145+
// [HttpPatch("{id}")]
146+
// [RequiredScopeOrAppPermission(
147+
// AcceptedScope = new string[] { "ToDoList.ReadWrite" },
148+
// AcceptedAppPermission = new string[] { "ToDoList.ReadWrite.All" })]
149+
// public IActionResult Patch(int id, [FromBody] Todo todo)
150+
// {
151+
// if (id != todo.Id || !TodoStore.Values.Any(x => x.Id == id))
152+
// {
153+
// return NotFound();
154+
// }
48155

49-
if (todoItem == null)
50-
{
51-
return NotFound();
52-
}
156+
// if (
157+
// HasDelegatedPermissions(new string[] { "ToDoList.ReadWrite" })
158+
// && TodoStore.Values.Any(x => x.Id == id && x.Owner == _contextAccessor.HttpContext.User.GetObjectId())
159+
// && todo.Owner == _contextAccessor.HttpContext.User.GetObjectId()
53160

54-
return todoItem;
55-
}
161+
// ||
56162

57-
// PUT: api/TodoItems/5
58-
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
59-
// more details see https://aka.ms/RazorPagesCRUD.
60-
[HttpPut("{id}")]
61-
public async Task<IActionResult> PutTodoItem(int id, TodoItem todoItem)
62-
{
63-
HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);
64-
65-
if (id != todoItem.Id)
66-
{
67-
return BadRequest();
68-
}
69-
70-
_context.Entry(todoItem).State = EntityState.Modified;
71-
72-
try
73-
{
74-
await _context.SaveChangesAsync();
75-
}
76-
catch (DbUpdateConcurrencyException)
77-
{
78-
if (!TodoItemExists(id))
79-
{
80-
return NotFound();
81-
}
82-
else
83-
{
84-
throw;
85-
}
86-
}
87-
88-
return NoContent();
89-
}
163+
// HasApplicationPermissions(new string[] { "ToDoList.ReadWrite.All" })
90164

91-
// POST: api/TodoItems
92-
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
93-
// more details see https://aka.ms/RazorPagesCRUD.
94-
[HttpPost]
95-
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
96-
{
97-
HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);
98-
string owner = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
99-
todoItem.Owner = owner;
100-
todoItem.Status = false;
165+
// )
166+
// {
167+
// TodoStore.Remove(id);
168+
// TodoStore.Add(id, todo);
101169

102-
_context.TodoItems.Add(todoItem);
103-
await _context.SaveChangesAsync();
170+
// return Ok(todo);
171+
// }
104172

105-
return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem);
106-
}
173+
// return BadRequest();
174+
// }
107175

108-
// DELETE: api/TodoItems/5
109-
[HttpDelete("{id}")]
110-
public async Task<ActionResult<TodoItem>> DeleteTodoItem(int id)
111-
{
112-
HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);
176+
// POST: api/TodoItems
177+
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
178+
// more details see https://aka.ms/RazorPagesCRUD.
179+
[HttpPost]
180+
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
181+
{
182+
HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);
183+
string owner = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
184+
todoItem.Owner = owner;
185+
todoItem.Status = false;
113186

114-
var todoItem = await _context.TodoItems.FindAsync(id);
115-
if (todoItem == null)
116-
{
117-
return NotFound();
118-
}
187+
_context.TodoItems.Add(todoItem);
188+
await _context.SaveChangesAsync();
119189

120-
_context.TodoItems.Remove(todoItem);
121-
await _context.SaveChangesAsync();
190+
return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem);
191+
}
122192

123-
return todoItem;
124-
}
193+
// [HttpPost]
194+
// [RequiredScopeOrAppPermission(
195+
// AcceptedScope = new string[] { "ToDoList.ReadWrite" },
196+
// AcceptedAppPermission = new string[] { "ToDoList.ReadWrite.All" })]
197+
// public IActionResult Post([FromBody] Todo todo)
198+
// {
199+
// var owner = _contextAccessor.HttpContext.User.GetObjectId();
125200

126-
private bool TodoItemExists(int id)
127-
{
128-
return _context.TodoItems.Any(e => e.Id == id);
129-
}
201+
// if (HasApplicationPermissions(new string[] { "ToDoList.ReadWrite.All" }))
202+
// {
203+
// //with such a permission any owner name is accepted from UI
204+
// owner = todo.Owner;
205+
// }
130206

131-
// Checks if the presented token has application permissions
132-
private bool HasApplicationPermissions(string[] permissionsNames)
133-
{
134-
var rolesClaim = User.Claims.Where(
135-
c => c.Type == ClaimConstants.Roles || c.Type == ClaimConstants.Role)
136-
.SelectMany(c => c.Value.Split(' '));
207+
// int id = TodoStore.Values.OrderByDescending(x => x.Id).FirstOrDefault().Id + 1;
208+
// Todo todonew = new Todo() { Id = id, Owner = owner, Title = todo.Title };
209+
// TodoStore.Add(id, todonew);
137210

138-
var result = rolesClaim.Any(v => permissionsNames.Any(p => p.Equals(v)));
211+
// return Ok(todo);
212+
// }
139213

140-
return result;
141-
}
214+
// DELETE: api/TodoItems/5
215+
[HttpDelete("{id}")]
216+
public async Task<ActionResult<TodoItem>> DeleteTodoItem(int id)
217+
{
218+
HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);
142219

143-
// Checks if the presented token has delegated permissions
144-
private bool HasDelegatedPermissions(string[] scopesNames)
145-
{
146-
var result = (User.FindFirst(ClaimConstants.Scp) ?? User.FindFirst(ClaimConstants.Scope))?
147-
.Value.Split(' ').Any(v => scopesNames.Any(s => s.Equals(v)));
220+
var todoItem = await _context.TodoItems.FindAsync(id);
221+
if (todoItem == null)
222+
{
223+
return NotFound();
224+
}
148225

149-
return result ?? false;
150-
}
226+
_context.TodoItems.Remove(todoItem);
227+
await _context.SaveChangesAsync();
228+
229+
return todoItem;
230+
}
231+
232+
// [HttpDelete("{id}")]
233+
// [RequiredScopeOrAppPermission(
234+
// AcceptedScope = new string[] { "ToDoList.ReadWrite" },
235+
// AcceptedAppPermission = new string[] { "ToDoList.ReadWrite.All" })]
236+
// public void Delete(int id)
237+
// {
238+
// if (
239+
// (
240+
241+
// HasDelegatedPermissions(new string[] { "ToDoList.ReadWrite" }) && TodoStore.Values.Any(x => x.Id == id && x.Owner == _contextAccessor.HttpContext.User.GetObjectId()))
242+
243+
// ||
244+
245+
// HasApplicationPermissions(new string[] { "ToDoList.ReadWrite.All" })
246+
// )
247+
// {
248+
// TodoStore.Remove(id);
249+
// }
250+
// }
251+
252+
private bool TodoItemExists(int id)
253+
{
254+
return _context.TodoItems.Any(e => e.Id == id);
255+
}
256+
257+
//Checks if the presented token has application permissions
258+
private bool HasApplicationPermissions(string[] permissionsNames)
259+
{
260+
var rolesClaim = User.Claims.Where(
261+
c => c.Type == ClaimConstants.Roles || c.Type == ClaimConstants.Role)
262+
.SelectMany(c => c.Value.Split(' '));
263+
264+
var result = rolesClaim.Any(v => permissionsNames.Any(p => p.Equals(v)));
265+
266+
return result;
267+
}
268+
269+
//Checks if the presented token has delegated permissions
270+
private bool HasDelegatedPermissions(string[] scopesNames)
271+
{
272+
var result = (User.FindFirst(ClaimConstants.Scp) ?? User.FindFirst(ClaimConstants.Scope))?
273+
.Value.Split(' ').Any(v => scopesNames.Any(s => s.Equals(v)));
274+
275+
return result ?? false;
151276
}
277+
}
152278
}

3-Authorization-II/1-call-api/API/TodoListAPI/Startup.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,9 @@ public void ConfigureServices(IServiceCollection services)
3030
// This flag ensures that the ClaimsIdentity claims collection will be built from the claims in the token
3131
JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
3232

33-
// Setting configuration for protected web api
33+
// Adds Microsoft Identity platform (AAD v2.0) support to protect this Api
3434
services.AddMicrosoftIdentityWebApiAuthentication(Configuration);
3535

36-
// Creating policies that wraps the authorization requirements
37-
services.AddAuthorization();
38-
3936
services.AddDbContext<TodoContext>(opt => opt.UseInMemoryDatabase("TodoList"));
4037

4138
services.AddControllers();

0 commit comments

Comments
 (0)