Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#34722] Add Authentication and Authorization to api routes #90

Merged
merged 25 commits into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
74eb33b
initial sanctum setup and concept api controller protection
nevinsm Sep 19, 2024
2eabaff
add sanctum middleware to api group, update controllers to protect ro…
nevinsm Sep 19, 2024
95eb616
add reconcile to methods allowed on concept controller without auth
nevinsm Sep 20, 2024
4487b0d
add role and permission models to application
nevinsm Sep 20, 2024
969e654
update isVocabularyEditor to use Permission model
nevinsm Sep 24, 2024
b5248dd
[#34722] add phpunit cache to gitignore
nevinsm Oct 13, 2024
5b053b6
[#34722] Scaffold out Concepts Authorization
nevinsm Oct 13, 2024
685c8d5
feat: Set up authorization for Concept model using policies and tests
nevinsm Oct 13, 2024
d16820e
update user factory for Laravel 11
nevinsm Oct 13, 2024
ce6fd0a
fix: Clean up example tests and concept test, simplify concept api co…
nevinsm Oct 13, 2024
e8e0df4
feat: Factories and model bindings for Term, Concept, and User
nevinsm Oct 16, 2024
ae2c437
formatting fix
nevinsm Oct 18, 2024
280fe23
feat: Working concept testing
nevinsm Oct 18, 2024
60fc862
feat: Create interactive artisan command to add user with role
nevinsm Oct 18, 2024
0dbe7e0
chore: concepts api controller comment cleanup
nevinsm Oct 21, 2024
e7b9f67
feat: Add TermPolicy for managing terms and conditions access
nevinsm Oct 21, 2024
2c111cb
feat: Add authorization for Term API in policy and controller
nevinsm Oct 21, 2024
405a054
refactor: Update TermController to use type hinting for Term model
nevinsm Oct 21, 2024
fb91e7b
fix: update return status for concept deletion
nevinsm Oct 21, 2024
9ff3d57
feat: Add Term API testing
nevinsm Oct 21, 2024
f02c447
refactor: Update TermController authorization
nevinsm Oct 21, 2024
0a288d6
feat: Add resource authorization to ConceptSourceController
nevinsm Oct 21, 2024
2297cfb
refactor: Update method signatures to type hint ConceptSource model
nevinsm Oct 21, 2024
523f067
feat: Add ConceptSources API testing
nevinsm Oct 21, 2024
ee59c0b
fix: Update type hinting to use correct variable name
nevinsm Oct 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ CACHE_DRIVER=file
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
SESSION_DOMAIN=.ddev.site

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
.env
.env.backup
.phpunit.result.cache
.phpunit.cache
Homestead.json
Homestead.yaml
npm-debug.log
Expand Down
39 changes: 39 additions & 0 deletions app/Console/Commands/AddUser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use App\Models\User;
use App\Models\Role;

class AddUser extends Command
{
protected $signature = 'user:add';

protected $description = 'Add a new user with a role';

public function handle()
{
$firstName = $this->ask('Enter the user\'s first name');
$lastName = $this->ask('Enter the user\'s last name');
$email = $this->ask('Enter the user\'s email');

// Fetch available roles
$roles = Role::all()->pluck('label')->toArray();
$role = $this->choice('Select a role for the user', $roles);

// Create the user
$user = User::create([
'first' => $firstName,
'last' => $lastName,
'fullname' => "{$firstName} {$lastName}",
'email' => $email,
'username' => $email,
]);

// Assign the role to the user
$user->assignRole($role); // Ensure you have a method to assign roles

$this->info("User {$firstName} {$lastName} with role {$role} has been created successfully.");
}
}
2 changes: 1 addition & 1 deletion app/Console/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class Kernel extends ConsoleKernel
* @var array
*/
protected $commands = [
//
\App\Console\Commands\AddUser::class,
];

/**
Expand Down
86 changes: 67 additions & 19 deletions app/Http/Controllers/API/ConceptController.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@

class ConceptController extends Controller
{
/**
* Instantiate a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth:sanctum')->except(['index', 'show', 'reconcile']);
$this->authorizeResource(Concept::class);
}

/**
* Display a listing of the resource.
*
Expand Down Expand Up @@ -102,7 +113,7 @@ public function store(ConceptStoreRequest $request)
DB::commit();
return response()->json([
"id" => $concept->id,
]);
], 201);
} catch (\Throwable $th) {
DB::rollback();

Expand All @@ -116,24 +127,23 @@ public function store(ConceptStoreRequest $request)
/**
* Display the specified resource.
*
* @param int $id
* @param \App\Concept $concept
* @return \Illuminate\Http\Response
*/
public function show($id)
public function show(Concept $concept)
{
return Concept::findOrFail($id);
return $concept;
}

/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @param \App\Concept $concept
* @return \Illuminate\Http\Response
*/
public function update(Request $request, int $id)
public function update(Request $request, Concept $concept)
{
$concept = Concept::findOrFail($id);
$attributes = $request->all();

// Sync concept categories
Expand All @@ -152,15 +162,50 @@ public function update(Request $request, int $id)
return new Response($concept);
}

/**
* Relate Concepts
*
* @param \Illuminate\Http\Request $request
* @param \App\Concept $concept
* @return \Illuminate\Http\Response
*/
public function relateConcepts(Request $request, Concept $concept)
{
if ($request->user()->cannot('update', $concept)) {
abort(403);
}

$relation_type = $request->input('relation_type');
$related_id = $request->input('related_id');

switch ($relation_type) {
case "broader":
$concept->addBroader($related_id);
break;
case "narrower":
$concept->addNarrower($related_id);
break;
case "related":
$concept->addRelated($related_id);
break;
}

return $concept;
}

/**
* Display the specified resource.
*
* @param int $id
* @param \Illuminate\Http\Request $request
* @param \App\Concept $concept
* @return \Illuminate\Http\Response
*/
public function deprecate(Request $request, $id)
public function deprecate(Request $request, Concept $concept)
{
$concept = Concept::findOrFail($id);
if ($request->user()->cannot('update', $concept)) {
abort(403);
}

$to = $request->input('to');
if ($to) {
$replaceConcept = Concept::findOrFail($to);
Expand All @@ -169,18 +214,23 @@ public function deprecate(Request $request, $id)
$concept->deprecated = !$concept->deprecated;
$concept->save();
}
return $concept->deprecated ? 'true' : 'false';

return response()->json($concept, 200);
}

/**
* Remove the specified resource from storage.
*
* @param int $id
* @param \App\Concept $concept
* @return \Illuminate\Http\Response
*/
public function destroy($id)
public function destroy(Concept $concept)
{
//
$concept->conceptCategories()->detach();
$concept->terms()->delete();
$concept->delete();

return response('Deleted ' . $concept->id, 204);
}

/**
Expand All @@ -199,11 +249,9 @@ public function reconcile(Request $request)
'category' => 'required',
]);

if (isset($request['category'])) {
$category_id = config('cache.category_ids')[$request['category']] ?? null;
$category = isset($category_id) ? $request['category'] : null;
}
$term = $_GET["term"];
$category_id = config('cache.category_ids')[$request->input('category')] ?? null;
$category = $category_id ? $request->input('category') : null;
$term = $request->input('term');

$terms = DB::table('concepts')->select('concepts.id as id', 'text as name')
->addSelect(DB::raw("true as match, 100 as score, '$category' as type"))
Expand Down
34 changes: 22 additions & 12 deletions app/Http/Controllers/API/ConceptSourceController.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,17 @@

class ConceptSourceController extends Controller
{
/**
* Instantiate a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth:sanctum')->except(['index', 'show']);
$this->authorizeResource(ConceptSource::class);
}

/**
* Display a listing of the resource.
*
Expand Down Expand Up @@ -62,37 +73,36 @@ public function store(Request $request)
/**
* Display the specified resource.
*
* @param int $id
* @param ConceptSource $conceptSource
* @return \Illuminate\Http\Response
*/
public function show($id)
public function show(ConceptSource $conceptSource)
{
return ConceptSource::findOrFail($id);
return $conceptSource;
}

/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @param ConceptSource $conceptSource
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
public function update(Request $request, ConceptSource $conceptSource)
{
$source = ConceptSource::findOrFail($id);
$source->update($request->all());
return $source;
$conceptSource->update($request->all());
return $conceptSource;
}

/**
* Remove the specified resource from storage.
*
* @param int $id
* @param ConceptSource $conceptSource
* @return \Illuminate\Http\Response
*/
public function destroy($id)
public function destroy(ConceptSource $conceptSource)
{
$source = ConceptSource::findOrFail($id)->delete();
return response('Deleted' . $id, 204);
$conceptSource->delete();
return response('Deleted ' . $conceptSource->id, 204);
}
}
32 changes: 21 additions & 11 deletions app/Http/Controllers/API/TermController.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,17 @@

class TermController extends Controller
{
/**
* Instantiate a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth:sanctum')->except(['index', 'show']);
$this->authorizeResource(Term::class);
}

/**
* Display a listing of the resource.
*
Expand Down Expand Up @@ -54,38 +65,37 @@ public function store(Request $request)
/**
* Display the specified resource.
*
* @param int $id
* @param \App\Models\Term $term
* @return \Illuminate\Http\Response
*/
public function show($id)
public function show(Term $term)
{
return Term::findOrFail($id);
return $term;
}

/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @param \App\Models\Term $term
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
public function update(Request $request, Term $term)
{
$term = Term::findOrFail($id);
$term->update($request->all());
return $term;
}

/**
* Remove the specified resource from storage.
*
* @param int $id
* @param \App\Models\Term $term
* @return \Illuminate\Http\Response
*/
public function destroy($id)
public function destroy(Term $term)
{
$term = Term::findOrFail($id)->delete();
return response('Deleted', 204);

$term->delete();

return response('Deleted ' . $term->id, 204);
}
}
29 changes: 0 additions & 29 deletions app/Http/Controllers/ConceptController.php
Original file line number Diff line number Diff line change
Expand Up @@ -223,33 +223,4 @@ public function search(Concept $concept)

return $terms->get();
}

/**
* Relate Concepts
*
* @param \App\Concept $concept
* @return \Illuminate\Http\Response
*/
public function relateConcepts($concept_id)
{
$relation_type = $_GET["relation_type"];
$related_id = $_GET["related_id"];

$concept = Concept::findOrFail($concept_id);

switch ($relation_type) {
case "broader":
$concept->addBroader($related_id);
break;
case "narrower":
$concept->addNarrower($related_id);
break;
case "related":
$concept->addRelated($related_id);
break;
}

return $concept;
}

}
Loading
Loading