Browse Source

WIP added api keys and user api endpoint

Arno 4 years ago
parent
commit
ecc3c66589

+ 141 - 0
app/Http/Controllers/Admin/ApplicationApiController.php

@@ -0,0 +1,141 @@
+<?php
+
+namespace App\Http\Controllers\Admin;
+
+use App\Http\Controllers\Controller;
+use App\Models\ApplicationApi;
+use Exception;
+use Illuminate\Contracts\Foundation\Application;
+use Illuminate\Contracts\View\Factory;
+use Illuminate\Contracts\View\View;
+use Illuminate\Http\JsonResponse;
+use Illuminate\Http\RedirectResponse;
+use Illuminate\Http\Request;
+use Illuminate\Http\Response;
+use Illuminate\Support\Str;
+
+class ApplicationApiController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return Application|Factory|View|Response
+     */
+    public function index()
+    {
+        return view('admin.api.index');
+    }
+
+    /**
+     * Show the form for creating a new resource.
+     *
+     * @return Application|Factory|View|Response
+     */
+    public function create()
+    {
+        return view('admin.api.create');
+    }
+
+    /**
+     * Store a newly created resource in storage.
+     *
+     * @param Request $request
+     * @return RedirectResponse
+     */
+    public function store(Request $request)
+    {
+        $request->validate([
+           'memo' => 'nullable|string|max:60'
+        ]);
+
+        ApplicationApi::create([
+            'memo' => $request->input('memo')
+        ]);
+
+        return redirect()->route('admin.api.index')->with('success', 'api key created!');
+    }
+
+    /**
+     * Display the specified resource.
+     *
+     * @param ApplicationApi $applicationApi
+     * @return Response
+     */
+    public function show(ApplicationApi $applicationApi)
+    {
+        //
+    }
+
+    /**
+     * Show the form for editing the specified resource.
+     *
+     * @param ApplicationApi $applicationApi
+     * @return Application|Factory|View|Response
+     */
+    public function edit(ApplicationApi $applicationApi)
+    {
+        return view('admin.api.edit' , [
+            'applicationApi' => $applicationApi
+        ]);
+    }
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param Request $request
+     * @param ApplicationApi $applicationApi
+     * @return RedirectResponse
+     */
+    public function update(Request $request, ApplicationApi $applicationApi)
+    {
+        $request->validate([
+            'memo' => 'nullable|string|max:60'
+        ]);
+
+        $applicationApi->update($request->all());
+
+        return redirect()->route('admin.api.index')->with('success', 'api key updated!');
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param ApplicationApi $applicationApi
+     * @return RedirectResponse
+     */
+    public function destroy(ApplicationApi $applicationApi)
+    {
+        $applicationApi->delete();
+        return redirect()->back()->with('success', 'api key has been removed!');
+    }
+
+    /**
+     * @param Request $request
+     * @return JsonResponse|mixed
+     * @throws Exception
+     */
+    public function dataTable(Request $request)
+    {
+        $query = ApplicationApi::query();
+
+        return datatables($query)
+            ->addColumn('actions', function (ApplicationApi $apiKey) {
+                return '
+                <a data-content="Edit" data-toggle="popover" data-trigger="hover" data-placement="top"  href="' . route('admin.api.edit', $apiKey->token) . '" class="btn btn-sm btn-info mr-1"><i class="fas fa-pen"></i></a>
+                <form class="d-inline" onsubmit="return submitResult();" method="post" action="' . route('admin.api.destroy', $apiKey->token) . '">
+                            ' . csrf_field() . '
+                            ' . method_field("DELETE") . '
+                           <button data-content="Delete" data-toggle="popover" data-trigger="hover" data-placement="top" class="btn btn-sm btn-danger mr-1"><i class="fas fa-trash"></i></button>
+                       </form>
+                ';
+            })
+            ->editColumn('token' , function (ApplicationApi $apiKey) {
+                return "<code>{$apiKey->token}</code>";
+            })
+            ->editColumn('last_used' , function (ApplicationApi $apiKey) {
+                return $apiKey->last_used ? $apiKey->last_used->diffForHumans() : '';
+            })
+            ->rawColumns(['actions' , 'token'])
+            ->make();
+    }
+}

+ 78 - 78
app/Http/Controllers/Api/UserController.php

@@ -1,79 +1,79 @@
 <?php
 <?php
-//
-//namespace App\Http\Controllers\Api;
-//
-//use App\Http\Controllers\Controller;
-//use App\Models\DiscordUser;
-//use App\Models\User;
-//use Illuminate\Contracts\Foundation\Application;
-//use Illuminate\Contracts\Routing\ResponseFactory;
-//use Illuminate\Http\Request;
-//use Illuminate\Http\Response;
-//use Illuminate\Validation\Rule;
-//
-//class UserController extends Controller
-//{
-//    /**
-//     * Display a listing of the resource.
-//     *
-//     * @return Response
-//     */
-//    public function index(Request $request)
-//    {
-//        return User::paginate($request->query('per_page') ?? 50);
-//    }
-//
-//
-//    /**
-//     * Display the specified resource.
-//     *
-//     * @param int $id
-//     * @return User
-//     */
-//    public function show(int $id)
-//    {
-//        $discordUser = DiscordUser::find($id);
-//        return $discordUser ? $discordUser->user : User::findOrFail($id);
-//    }
-//
-//
-//    /**
-//     * Update the specified resource in storage.
-//     *
-//     * @param Request $request
-//     * @param int $id
-//     * @return User
-//     */
-//    public function update(Request $request, int $id)
-//    {
-//        $discordUser = DiscordUser::find($id);
-//        $user = $discordUser ? $discordUser->user : User::findOrFail($id);
-//
-//        $request->validate([
-//            "name"         => "sometimes|string|min:4|max:30",
-//            "email"        => "sometimes|string|email",
-//            "credits"      => "sometimes|numeric|min:0|max:1000000",
-//            "server_limit" => "sometimes|numeric|min:0|max:1000000",
-//            "role"         => ['sometimes', Rule::in(['admin', 'mod', 'client', 'member'])],
-//        ]);
-//
-//        $user->update($request->all());
-//
-//        return $user;
-//    }
-//
-//    /**
-//     * Remove the specified resource from storage.
-//     *
-//     * @param int $id
-//     * @return Application|ResponseFactory|Response|void
-//     */
-//    public function destroy(int $id)
-//    {
-//        $discordUser = DiscordUser::find($id);
-//        $user = $discordUser ? $discordUser->user : User::findOrFail($id);
-//
-//        $user->delete();
-//        return response($user, 200);
-//    }
-//}
+
+namespace App\Http\Controllers\Api;
+
+use App\Http\Controllers\Controller;
+use App\Models\DiscordUser;
+use App\Models\User;
+use Illuminate\Contracts\Foundation\Application;
+use Illuminate\Contracts\Routing\ResponseFactory;
+use Illuminate\Http\Request;
+use Illuminate\Http\Response;
+use Illuminate\Validation\Rule;
+
+class UserController extends Controller
+{
+    /**
+     * Display a listing of the resource.
+     *
+     * @return Response
+     */
+    public function index(Request $request)
+    {
+        return User::paginate($request->query('per_page') ?? 50);
+    }
+
+
+    /**
+     * Display the specified resource.
+     *
+     * @param int $id
+     * @return User
+     */
+    public function show(int $id)
+    {
+        $discordUser = DiscordUser::find($id);
+        return $discordUser ? $discordUser->user : User::findOrFail($id);
+    }
+
+
+    /**
+     * Update the specified resource in storage.
+     *
+     * @param Request $request
+     * @param int $id
+     * @return User
+     */
+    public function update(Request $request, int $id)
+    {
+        $discordUser = DiscordUser::find($id);
+        $user = $discordUser ? $discordUser->user : User::findOrFail($id);
+
+        $request->validate([
+            "name"         => "sometimes|string|min:4|max:30",
+            "email"        => "sometimes|string|email",
+            "credits"      => "sometimes|numeric|min:0|max:1000000",
+            "server_limit" => "sometimes|numeric|min:0|max:1000000",
+            "role"         => ['sometimes', Rule::in(['admin', 'mod', 'client', 'member'])],
+        ]);
+
+        $user->update($request->all());
+
+        return $user;
+    }
+
+    /**
+     * Remove the specified resource from storage.
+     *
+     * @param int $id
+     * @return Application|ResponseFactory|Response|void
+     */
+    public function destroy(int $id)
+    {
+        $discordUser = DiscordUser::find($id);
+        $user = $discordUser ? $discordUser->user : User::findOrFail($id);
+
+        $user->delete();
+        return response($user, 200);
+    }
+}

+ 1 - 1
app/Http/Controllers/Auth/RegisterController.php

@@ -58,7 +58,7 @@ class RegisterController extends Controller
 
 
         //check if registered cookie exists as extra defense
         //check if registered cookie exists as extra defense
         if (isset($_COOKIE['4b3403665fea6'])) {
         if (isset($_COOKIE['4b3403665fea6'])) {
-            $data['registered'] = true;
+            $data['registered'] = env('APP_ENV') == 'local' ? false : true;
         }
         }
 
 
         return Validator::make($data, [
         return Validator::make($data, [

+ 3 - 1
app/Http/Kernel.php

@@ -2,6 +2,7 @@
 
 
 namespace App\Http;
 namespace App\Http;
 
 
+use App\Http\Middleware\ApiAuthToken;
 use App\Http\Middleware\isAdmin;
 use App\Http\Middleware\isAdmin;
 use App\Http\Middleware\LastSeen;
 use App\Http\Middleware\LastSeen;
 use Illuminate\Foundation\Http\Kernel as HttpKernel;
 use Illuminate\Foundation\Http\Kernel as HttpKernel;
@@ -65,6 +66,7 @@ class Kernel extends HttpKernel
         'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
         'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
         'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
         'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
         'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
         'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
-        'admin' => isAdmin::class
+        'admin' => isAdmin::class,
+        'api.token' => ApiAuthToken::class
     ];
     ];
 }
 }

+ 25 - 0
app/Http/Middleware/ApiAuthToken.php

@@ -0,0 +1,25 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use App\Models\ApplicationApi;
+use Closure;
+use Illuminate\Http\Request;
+
+class ApiAuthToken
+{
+    /**
+     * Handle an incoming request.
+     *
+     * @param Request $request
+     * @param Closure $next
+     * @return mixed
+     */
+    public function handle(Request $request, Closure $next)
+    {
+        $token = ApplicationApi::find($request->bearerToken());
+        if (is_null($token)) return response()->json(['message' => 'Invalid Authorization token'], 401);
+        $token->updateLastUsed();
+        return $next($request);
+    }
+}

+ 35 - 0
app/Models/ApplicationApi.php

@@ -0,0 +1,35 @@
+<?php
+
+namespace App\Models;
+
+use Hidehalo\Nanoid\Client;
+use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Model;
+
+class ApplicationApi extends Model
+{
+    use HasFactory;
+
+    protected $fillable = ['token', 'memo' , 'last_used'];
+
+    protected $primaryKey = 'token';
+
+    public $incrementing = false;
+
+    protected $dates = ['last_used'];
+
+    public static function boot()
+    {
+        parent::boot();
+
+        static::creating(function (ApplicationApi $applicationApi) {
+            $client = new Client();
+
+            $applicationApi->{$applicationApi->getKeyName()} = $client->generateId(48);
+        });
+    }
+
+    public function updateLastUsed(){
+        $this->update(['last_used' => now()]);
+    }
+}

+ 28 - 0
database/factories/ApplicationApiFactory.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace Database\Factories;
+
+use App\Models\ApplicationApi;
+use Illuminate\Database\Eloquent\Factories\Factory;
+
+class ApplicationApiFactory extends Factory
+{
+    /**
+     * The name of the factory's corresponding model.
+     *
+     * @var string
+     */
+    protected $model = ApplicationApi::class;
+
+    /**
+     * Define the model's default state.
+     *
+     * @return array
+     */
+    public function definition()
+    {
+        return [
+            //
+        ];
+    }
+}

+ 33 - 0
database/migrations/2021_06_06_144120_create_application_apis_table.php

@@ -0,0 +1,33 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateApplicationApisTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('application_apis', function (Blueprint $table) {
+            $table->string('token')->unique()->primary();
+            $table->string('memo')->nullable();
+            $table->timestamp('last_used')->nullable();
+            $table->timestamps();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('application_apis');
+    }
+}

+ 63 - 0
resources/views/admin/api/create.blade.php

@@ -0,0 +1,63 @@
+@extends('layouts.main')
+
+@section('content')
+    <!-- CONTENT HEADER -->
+    <section class="content-header">
+        <div class="container-fluid">
+            <div class="row mb-2">
+                <div class="col-sm-6">
+                    <h1>Application API</h1>
+                </div>
+                <div class="col-sm-6">
+                    <ol class="breadcrumb float-sm-right">
+                        <li class="breadcrumb-item"><a href="{{route('home')}}">Dashboard</a></li>
+                        <li class="breadcrumb-item"><a href="{{route('admin.api.index')}}">Application API</a></li>
+                        <li class="breadcrumb-item"><a class="text-muted" href="{{route('admin.api.create')}}">Create</a>
+                        </li>
+                    </ol>
+                </div>
+            </div>
+        </div>
+    </section>
+    <!-- END CONTENT HEADER -->
+
+    <!-- MAIN CONTENT -->
+    <section class="content">
+        <div class="container-fluid">
+
+            <div class="row">
+                <div class="col-lg-6">
+                    <div class="card">
+                        <div class="card-body">
+                            <form action="{{route('admin.api.store')}}" method="POST">
+                                @csrf
+
+                                <div class="form-group">
+                                    <label for="memo">Memo</label>
+                                    <input value="{{old('memo')}}" id="memo" name="memo" type="text"
+                                           class="form-control @error('memo') is-invalid @enderror">
+                                    @error('memo')
+                                    <div class="invalid-feedback">
+                                        {{$message}}
+                                    </div>
+                                    @enderror
+                                </div>
+
+                                <div class="form-group text-right">
+                                    <button type="submit" class="btn btn-primary">
+                                        Submit
+                                    </button>
+                                </div>
+                            </form>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+    </section>
+    <!-- END CONTENT -->
+
+
+
+@endsection

+ 64 - 0
resources/views/admin/api/edit.blade.php

@@ -0,0 +1,64 @@
+@extends('layouts.main')
+
+@section('content')
+    <!-- CONTENT HEADER -->
+    <section class="content-header">
+        <div class="container-fluid">
+            <div class="row mb-2">
+                <div class="col-sm-6">
+                    <h1>Application API</h1>
+                </div>
+                <div class="col-sm-6">
+                    <ol class="breadcrumb float-sm-right">
+                        <li class="breadcrumb-item"><a href="{{route('home')}}">Dashboard</a></li>
+                        <li class="breadcrumb-item"><a href="{{route('admin.api.index')}}">Application API</a></li>
+                        <li class="breadcrumb-item"><a class="text-muted" href="{{route('admin.api.edit'  , $applicationApi->token)}}">Edit</a>
+                        </li>
+                    </ol>
+                </div>
+            </div>
+        </div>
+    </section>
+    <!-- END CONTENT HEADER -->
+
+    <!-- MAIN CONTENT -->
+    <section class="content">
+        <div class="container-fluid">
+
+            <div class="row">
+                <div class="col-lg-6">
+                    <div class="card">
+                        <div class="card-body">
+                            <form action="{{route('admin.api.update' , $applicationApi->token)}}" method="POST">
+                                @csrf
+                                @method('PATCH')
+
+                                <div class="form-group">
+                                    <label for="memo">Memo</label>
+                                    <input value="{{$applicationApi->memo}}" id="memo" name="memo" type="text"
+                                           class="form-control @error('memo') is-invalid @enderror">
+                                    @error('memo')
+                                    <div class="invalid-feedback">
+                                        {{$message}}
+                                    </div>
+                                    @enderror
+                                </div>
+
+                                <div class="form-group text-right">
+                                    <button type="submit" class="btn btn-primary">
+                                        Submit
+                                    </button>
+                                </div>
+                            </form>
+                        </div>
+                    </div>
+                </div>
+            </div>
+
+        </div>
+    </section>
+    <!-- END CONTENT -->
+
+
+
+@endsection

+ 87 - 0
resources/views/admin/api/index.blade.php

@@ -0,0 +1,87 @@
+@extends('layouts.main')
+
+@section('content')
+    <!-- CONTENT HEADER -->
+    <section class="content-header">
+        <div class="container-fluid">
+            <div class="row mb-2">
+                <div class="col-sm-6">
+                    <h1>Application API</h1>
+                </div>
+                <div class="col-sm-6">
+                    <ol class="breadcrumb float-sm-right">
+                        <li class="breadcrumb-item"><a href="{{route('home')}}">Dashboard</a></li>
+                        <li class="breadcrumb-item"><a class="text-muted" href="{{route('admin.api.index')}}">Application API</a></li>
+                    </ol>
+                </div>
+            </div>
+        </div>
+    </section>
+    <!-- END CONTENT HEADER -->
+
+    <!-- MAIN CONTENT -->
+    <section class="content">
+        <div class="container-fluid">
+
+            <div class="card">
+
+                <div class="card-header">
+                    <div class="d-flex justify-content-between">
+                        <h5 class="card-title"><i class="fa fa-gamepad mr-2"></i>Application API</h5>
+                        <a href="{{route('admin.api.create')}}" class="btn btn-sm btn-primary"><i
+                                class="fas fa-plus mr-1"></i>Create new</a>
+                    </div>
+                </div>
+
+                <div class="card-body table-responsive">
+
+                    <table id="datatable" class="table table-striped">
+                        <thead>
+                        <tr>
+                            <th>Token</th>
+                            <th>Memo</th>
+                            <th>Last used</th>
+                            <th></th>
+                        </tr>
+                        </thead>
+                        <tbody>
+                        </tbody>
+                    </table>
+
+                </div>
+            </div>
+
+
+        </div>
+        <!-- END CUSTOM CONTENT -->
+    </section>
+    <!-- END CONTENT -->
+
+    <script>
+        function submitResult() {
+            return confirm("Are you sure you wish to delete?") !== false;
+        }
+
+        document.addEventListener("DOMContentLoaded", function () {
+            $('#datatable').DataTable({
+                processing: true,
+                serverSide: true,
+                stateSave: true,
+                ajax: "{{route('admin.api.datatable')}}",
+                order: [[ 2, "desc" ]],
+                columns: [
+                    {data: 'token'},
+                    {data: 'memo'},
+                    {data: 'last_used'},
+                    {data: 'actions' , sortable : false},
+                ],
+                fnDrawCallback: function( oSettings ) {
+                    $('[data-toggle="popover"]').popover();
+                }
+            });
+        });
+    </script>
+
+
+
+@endsection

+ 8 - 0
resources/views/layouts/main.blade.php

@@ -218,6 +218,14 @@
 
 
                         <li class="nav-header">Dashboard</li>
                         <li class="nav-header">Dashboard</li>
 
 
+                        <li class="nav-item">
+                            <a href="{{route('admin.api.index')}}"
+                               class="nav-link @if(Request::routeIs('admin.api.*')) active @endif">
+                                <i class="nav-icon fa fa-gamepad"></i>
+                                <p>Application API</p>
+                            </a>
+                        </li>
+
                         <li class="nav-item">
                         <li class="nav-item">
                             <a href="{{route('admin.configurations.index')}}"
                             <a href="{{route('admin.configurations.index')}}"
                                class="nav-link @if(Request::routeIs('admin.configurations.*')) active @endif">
                                class="nav-link @if(Request::routeIs('admin.configurations.*')) active @endif">

+ 4 - 2
routes/api.php

@@ -1,6 +1,6 @@
 <?php
 <?php
 
 
-//use App\Http\Controllers\Api\UserController;
+use App\Http\Controllers\Api\UserController;
 use App\Http\Controllers\Api\VerifyController;
 use App\Http\Controllers\Api\VerifyController;
 use Illuminate\Http\Request;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Route;
 use Illuminate\Support\Facades\Route;
@@ -20,7 +20,9 @@ Route::post('/verify' , [VerifyController::class , 'verify']);
 Route::middleware('auth:api')->get('/user', function (Request $request) {
 Route::middleware('auth:api')->get('/user', function (Request $request) {
     return $request->user();
     return $request->user();
 });
 });
+Route::middleware('api.token')->group(function(){
+    Route::resource('users' , UserController::class);
+});
 
 
-//Route::resource('users' , UserController::class);
 
 
 
 

+ 6 - 0
routes/web.php

@@ -1,6 +1,7 @@
 <?php
 <?php
 
 
 use App\Http\Controllers\Admin\ActivityLogController;
 use App\Http\Controllers\Admin\ActivityLogController;
+use App\Http\Controllers\Admin\ApplicationApiController;
 use App\Http\Controllers\Admin\ConfigurationController;
 use App\Http\Controllers\Admin\ConfigurationController;
 use App\Http\Controllers\Admin\NestsController;
 use App\Http\Controllers\Admin\NestsController;
 use App\Http\Controllers\Admin\NodeController;
 use App\Http\Controllers\Admin\NodeController;
@@ -99,6 +100,11 @@ Route::middleware('auth')->group(function () {
 
 
         Route::patch('settings/update/icons', [SettingsController::class , 'updateIcons'])->name('settings.update.icons');
         Route::patch('settings/update/icons', [SettingsController::class , 'updateIcons'])->name('settings.update.icons');
         Route::resource('settings', SettingsController::class)->only('index');
         Route::resource('settings', SettingsController::class)->only('index');
+
+        Route::get('api/datatable', [ApplicationApiController::class, 'datatable'])->name('api.datatable');
+        Route::resource('api', ApplicationApiController::class)->parameters([
+            'api' => 'applicationApi',
+        ]);
     });
     });
 
 
     Route::get('/home', [HomeController::class, 'index'])->name('home');
     Route::get('/home', [HomeController::class, 'index'])->name('home');