|
11 | 11 | using Microsoft.Identity.Web; |
12 | 12 | using Microsoft.Identity.Web.Resource; |
13 | 13 |
|
| 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 | + |
14 | 27 | namespace TodoListAPI.Controllers |
15 | 28 | { |
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) |
20 | 116 | { |
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 | + } |
24 | 123 |
|
25 | | - private readonly TodoContext _context; |
| 124 | + _context.Entry(todoItem).State = EntityState.Modified; |
26 | 125 |
|
27 | | - public TodoListController(TodoContext context) |
| 126 | + try |
| 127 | + { |
| 128 | + await _context.SaveChangesAsync(); |
| 129 | + } |
| 130 | + catch (DbUpdateConcurrencyException) |
| 131 | + { |
| 132 | + if (!TodoItemExists(id)) |
28 | 133 | { |
29 | | - _context = context; |
| 134 | + return NotFound(); |
30 | 135 | } |
31 | | - |
32 | | - // GET: api/TodoItems |
33 | | - [HttpGet] |
34 | | - public async Task<ActionResult<IEnumerable<TodoItem>>> GetTodoItems() |
| 136 | + else |
35 | 137 | { |
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; |
39 | 139 | } |
| 140 | + } |
40 | 141 |
|
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 | + } |
46 | 144 |
|
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 | + // } |
48 | 155 |
|
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() |
53 | 160 |
|
54 | | - return todoItem; |
55 | | - } |
| 161 | + // || |
56 | 162 |
|
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" }) |
90 | 164 |
|
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); |
101 | 169 |
|
102 | | - _context.TodoItems.Add(todoItem); |
103 | | - await _context.SaveChangesAsync(); |
| 170 | + // return Ok(todo); |
| 171 | + // } |
104 | 172 |
|
105 | | - return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem); |
106 | | - } |
| 173 | + // return BadRequest(); |
| 174 | + // } |
107 | 175 |
|
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; |
113 | 186 |
|
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(); |
119 | 189 |
|
120 | | - _context.TodoItems.Remove(todoItem); |
121 | | - await _context.SaveChangesAsync(); |
| 190 | + return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem); |
| 191 | + } |
122 | 192 |
|
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(); |
125 | 200 |
|
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 | + // } |
130 | 206 |
|
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); |
137 | 210 |
|
138 | | - var result = rolesClaim.Any(v => permissionsNames.Any(p => p.Equals(v))); |
| 211 | + // return Ok(todo); |
| 212 | + // } |
139 | 213 |
|
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); |
142 | 219 |
|
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 | + } |
148 | 225 |
|
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; |
151 | 276 | } |
| 277 | + } |
152 | 278 | } |
0 commit comments