Skip to content
Snippets Groups Projects
Unverified Commit cdccd23c authored by Maxime FRIESS's avatar Maxime FRIESS :blue_heart:
Browse files

[release] 1.1.0

parents dc9b6d42 c5619ff9
Branches
Tags 1.1.0
No related merge requests found
Pipeline #101157 passed with stages
in 51 seconds
Showing
with 1706 additions and 0 deletions
vendor
.git
.env
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2
[docker-compose.yml]
indent_size = 4
APP_NAME=Bombernyan-api
APP_ENV=prod
APP_KEY=
APP_DEBUG=false
APP_URL=https://mai-projet-integrateur.u-strasbg.fr/vmProjetIntegrateurgrp7-0
L5_SWAGGER_CONST_HOST=https://mai-projet-integrateur.u-strasbg.fr/vmProjetIntegrateurgrp7-0/
PMA_ABSOLUTE_URI=https://mai-projet-integrateur.u-strasbg.fr/vmProjetIntegrateurgrp7-0/pma/
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=mysql
DB_HOST=database
DB_PORT=3306
DB_DATABASE=bombernyan
DB_USERNAME=bombernyan
DB_PASSWORD=bombernyan
MARIADB_ROOT_PASSWORD=
MARIADB_DATABASE=bombernyan
MARIADB_USER=bombernyan
MARIADB_PASSWORD=bombernyan
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DISK=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="Bombernyan"
JWT_SECRET=
APP_NAME=Laravel
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=sqlite
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DISK=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_HOST=
PUSHER_PORT=443
PUSHER_SCHEME=https
PUSHER_APP_CLUSTER=mt1
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
VITE_PUSHER_HOST="${PUSHER_HOST}"
VITE_PUSHER_PORT="${PUSHER_PORT}"
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
APP_NAME=Laravel
APP_ENV=local
APP_KEY=base64:XCjE9IqkrLOfSE989JKob9PTbVWxZrvWXfyNHalhrlc=
APP_DEBUG=false
APP_URL=http://localhost
LOG_CHANNEL=stack
LOG_DEPRECATIONS_CHANNEL=null
LOG_LEVEL=debug
DB_CONNECTION=sqlite
BROADCAST_DRIVER=log
CACHE_DRIVER=file
FILESYSTEM_DISK=local
QUEUE_CONNECTION=sync
SESSION_DRIVER=file
SESSION_LIFETIME=120
MEMCACHED_HOST=127.0.0.1
REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=
AWS_USE_PATH_STYLE_ENDPOINT=false
PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_HOST=
PUSHER_PORT=443
PUSHER_SCHEME=https
PUSHER_APP_CLUSTER=mt1
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
VITE_PUSHER_HOST="${PUSHER_HOST}"
VITE_PUSHER_PORT="${PUSHER_PORT}"
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
JWT_SECRET=1nTDX71DXyIr6YM9soRu8eba3Jaa7mlZTXHUYlwg5ZqInBZF8kVKglpr5wynAMTU
JWT_ALGO=HS256
* text=auto
*.blade.php diff=html
*.css diff=css
*.html diff=html
*.md diff=markdown
*.php diff=php
/.github export-ignore
CHANGELOG.md export-ignore
.styleci.yml export-ignore
/node_modules
/public/build
/public/hot
/public/storage
/storage/*.key
/storage/api-docs/api-docs.json
/vendor
.env
.env.backup
.env.production
.env.docker
.phpunit.result.cache
Homestead.json
Homestead.yaml
auth.json
npm-debug.log
yarn-error.log
/.fleet
/.idea
/.vscode
*.sqlite
.gitlab-ci-local/
/public/index.html
/public/openapi.json
\ No newline at end of file
image: php:latest
stages:
- test
cache:
- key:
files:
- composer.lock
paths:
- vendor/
tests:
stage: test
coverage: '/Total Coverage\s\.+\s(\d+\.?\d+)/'
before_script:
- curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
- apt-get update
- apt-get install -y git unzip
- composer install
- pecl install xdebug
- docker-php-ext-enable xdebug
- echo "xdebug.mode=coverage" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
script:
- touch database/database.sqlite
- php artisan test --coverage
pages:
before_script:
- curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
- apt-get update
- apt-get install -y git unzip
- composer install
script:
- php artisan l5-swagger:generate
- cp doc/apidoc.html public/index.html
- cp storage/api-docs/api-docs.json public/openapi.json
artifacts:
paths:
- public/openapi.json
- public/index.html
FROM docker.io/php:8.2-fpm
# Add composer.lock and composer.json into the working directory
ADD composer.lock composer.json /api/
# Set working directory
WORKDIR /api/
# Install dependencies for the operating system software
RUN apt-get update && apt-get install -y \
build-essential \
libpng-dev \
libjpeg62-turbo-dev \
libfreetype6-dev \
locales \
zip \
jpegoptim optipng pngquant gifsicle \
vim \
libzip-dev \
unzip \
git \
libonig-dev \
curl \
cron
# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*
# Install extensions for php
RUN docker-php-ext-install pdo_mysql mbstring zip exif pcntl
RUN docker-php-ext-configure gd --with-freetype --with-jpeg
RUN docker-php-ext-install gd
# Install composer (php package manager)
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
# Add existing application directory contents to the working directory
ADD . /api
# Assign permissions of the working directory to the www-data user
RUN chown -R www-data:www-data \
/api/storage \
/api/bootstrap/cache
# Install dependencies
RUN composer install
# Build the doc
RUN php artisan l5-swagger:generate
# Add running laravel's scheduler in crontab
RUN echo "* * * * * cd /api && php artisan schedule:run >> /dev/null 2>&1" | crontab -
# Expose port 9000 and start php-fpm server (for FastCGI Process Manager)
# EXPOSE 9000
# CMD ["php-fpm"]
# Export port 9000 and start php artisan serve
EXPOSE 8000
CMD php artisan serve --host=0.0.0.0 --port=8000
README.md 0 → 100644
# BomberNyan API
## Getting Started
First, install php8 and composer, then clone the repository. You should now copy `.env.example` to `.env` and make the required edits.
The example configuration should work out of the box and uses an sqlite database.
You should then run the following commands:
```bash
# Install all the dependencies
composer install
# Generate the JWT secret
php artisan jwt:secret
# Create the sqlite database.
touch database/database.sqlite
# Run all the migrations on the database
php artisan migrate
```
To start the development server, you can now run
```
php artisan serve
```
## Generating the API documentation
The API generation can be generated with
```
php artisan l5-swagger:generate
```
Once you start the development server, you can access it at [http://127.0.0.1:8000/api/documentation](http://127.0.0.1:8000/api/documentation)
## Running the unit tests
The unit tests can be run with
```
php artisan test
```
## Running using Docker
To run the API using docker, you first need to copy `.env.docker.example` to `.env.docker` and make the necessary changes.
You can then build the API's Docker container:
```
docker compose build
```
To start the API, run:
```
docker compose up
```
To completely stop it, run:
```
docker compose down
```
You can also use this command to clean the volumes:
```
docker volume rm api_database
docker volume rm api_storage
```
Warning: This will remove all the data used by the API (database and storage).
## Deploying
Start by installing Docker and Docker compose on your production machine.
```
### Docker and docker compose prerequisites
sudo apt-get install curl
sudo apt-get install gnupg
sudo apt-get install ca-certificates
sudo apt-get install lsb-release
### Download the docker gpg file to Ubuntu
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
### Add Docker and docker compose support to the Ubuntu's packages list
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
### Install docker and docker compose on Ubuntu
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
```
Create a new system user with a home repository, and copy this repository's `docker-compose.yml`, `.env.docker.example` and `nginx.conf` to its home folder. Be sure to rename `.env.docker.example` to `.env.docker` and edit to edit the config files to your likings.
Since we will be deploying from images in the repository, be sure to edit `docker-compose.yml` and to remove the `build: .` line in the api service.
Download all the images used by the api:
```
docker compose pull
```
You should now be able to launch the API by running
```
docker compose up
```
We will now add a systemd unit at `/etc/systemd/system/api.service`:
```
[Unit]
Description=BomberNyan API
After=multi-user.target
[Service]
Type=simple
User=api
Group=api
Restart=always
ExecStart=/usr/bin/docker compose up
ExecStop=/usr/bin/docker compose down
WorkingDirectory=/srv/api/
[Install]
WantedBy=multi-user.target
```
You can then start and enable that systemd unit
```
sudo systemctl enable api
sudo systemctl start api
```
The API should now run as a service.
You should also edit `/etc/docker/daemon.json` to tell Docker to use journald as its log driver:
```
{
"log-driver": "journald"
}
```
This allows you to see the container's logs with
```
sudo journalctl -feu docker
```
<?php
namespace App\Console;
use App\Jobs\CheckServers;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')->hourly();
$schedule->job(new CheckServers)->everyMinute();
}
/**
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__.'/Commands');
require base_path('routes/console.php');
}
}
<?php
namespace App\Exceptions;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;
class Handler extends ExceptionHandler
{
/**
* A list of exception types with their corresponding custom log levels.
*
* @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*>
*/
protected $levels = [
//
];
/**
* A list of the exception types that are not reported.
*
* @var array<int, class-string<\Throwable>>
*/
protected $dontReport = [
//
];
/**
* A list of the inputs that are never flashed to the session on validation exceptions.
*
* @var array<int, string>
*/
protected $dontFlash = [
'current_password',
'password',
'password_confirmation',
];
/**
* Register the exception handling callbacks for the application.
*
* @return void
*/
public function register()
{
$this->reportable(function (Throwable $e) {
//
});
}
}
<?php
namespace App\Http\Controllers\Client;
use App\Http\Controllers\Controller;
use App\Http\Requests\LoginRequest;
use App\Http\Requests\RecoverAccountRequest;
use App\Http\Requests\RegisterRequest;
use Illuminate\Auth\Events\Registered;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use App\Models\User;
use Illuminate\Support\Facades\Password;
class AuthController extends Controller
{
/**
* @OA\Post(
* tags={"Clients:Authentication"},
* path="/auth/login",
* summary="Login to the API",
* @OA\RequestBody(
* ref="#/components/requestBodies/Login"
* ),
* @OA\Response(
* response="401",
* ref="#/components/responses/401"
* ),
* @OA\Response(
* response="422",
* ref="#/components/responses/422"
* ),
* @OA\Response(
* response="200",
* description="OK",
* @OA\JsonContent(
* @OA\Property(
* property="token",
* type="string",
* description="Token to use as Bearer token",
* ),
* @OA\Property(
* property="user",
* type="object",
* allOf={
* @OA\Schema(ref="#/components/schemas/User"),
* @OA\Schema(
* @OA\Property(type="string", property="email", format="email"),
* )
* }
* ),
* ),
* ),
* )
*/
public function login(LoginRequest $request)
{
$token = Auth::guard('client')->attempt($request->validated());
if (!$token) {
return response()->json([
'message' => 'Unauthorized',
], 401);
}
$user = Auth::guard('client')->user();
if (!$user->hasVerifiedEmail()) {
return response()->json([
'message' => 'Please verify your email',
], 401);
}
return response()->json([
'user' => $user->makeVisible('email'),
'token' => $token,
]);
}
/**
* @OA\Post(
* tags={"Clients:Authentication"},
* path="/auth/register",
* summary="Register to the API",
* @OA\RequestBody(
* ref="#/components/requestBodies/Register"
* ),
* @OA\Response(
* response="401",
* ref="#/components/responses/401"
* ),
* @OA\Response(
* response="422",
* ref="#/components/responses/422"
* ),
* @OA\Response(
* response="204",
* description="OK"
* ),
* )
*/
public function register(RegisterRequest $request)
{
$user = User::create([
'username' => $request->username,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
$token = Auth::guard('client')->login($user);
event(new Registered($user));
return response()->noContent();
}
/**
* @OA\Post(
* tags={"Clients:Authentication"},
* path="/auth/logout",
* summary="Logout of the API",
* @OA\Response(
* response="401",
* ref="#/components/responses/401"
* ),
* @OA\Response(
* response="204",
* description="OK",
* ),
* security={{"jwt":{}}},
* )
*/
public function logout()
{
Auth::guard('client')->logout();
return response()->noContent();
}
/**
* @OA\Post(
* tags={"Clients:Authentication"},
* path="/auth/refresh",
* summary="Refresh an API token",
* @OA\Response(
* response="401",
* ref="#/components/responses/401"
* ),
* @OA\Response(
* response="200",
* description="OK",
* @OA\JsonContent(
* @OA\Property(
* property="token",
* type="string",
* description="Token to use as Bearer token",
* ),
* @OA\Property(
* property="user",
* type="object",
* allOf={
* @OA\Schema(ref="#/components/schemas/User"),
* @OA\Schema(
* @OA\Property(type="string", property="email", format="email"),
* )
* }
* ),
* ),
* ),
* security={{"jwt":{}}},
* )
*/
public function refresh()
{
return response()->json([
'user' => Auth::guard('client')->user()->makeVisible('email'),
'token' => Auth::guard('client')->refresh(),
]);
}
/**
* @OA\Post(
* tags={"Clients:Authentication"},
* path="/auth/recover",
* summary="Recover an account",
* @OA\RequestBody(
* ref="#/components/requestBodies/RecoverAccount"
* ),
* @OA\Response(
* response="422",
* ref="#/components/responses/422"
* ),
* @OA\Response(
* response="429",
* description="Too Many Requests",
* @OA\JsonContent(
* @OA\Property(
* property="message",
* type="string",
* ),
* )
* ),
* @OA\Response(
* response="204",
* description="OK",
* ),
* )
*/
public function recover(RecoverAccountRequest $request)
{
$status = Password::sendResetLink(
$request->only('email')
);
if ($status === Password::RESET_LINK_SENT) {
return response()->noContent();
} else if ($status === Password::INVALID_USER) {
return response()->json([
'message' => __($status),
], 401);
} else if ($status === Password::RESET_THROTTLED) {
return response()->json([
'message' => __($status),
], 429);
}
}
}
<?php
namespace App\Http\Controllers\Client;
use App\Http\Controllers\Controller;
use App\Http\Requests\ConnectRequest;
use App\Models\Server;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
class ConnectController extends Controller
{
/**
* @OA\Post(
* tags={"Clients:Server"},
* path="/server/{id}/connect",
* summary="Connect to a server",
* @OA\Parameter(
* name="id",
* in="path",
* required=true,
* @OA\Schema(type="integer")
* ),
* @OA\RequestBody(
* ref="#/components/requestBodies/Connect"
* ),
* @OA\Response(
* response="401",
* ref="#/components/responses/401"
* ),
* @OA\Response(
* response="403",
* description="Forbidden",
* @OA\JsonContent(
* @OA\Property(
* property="message",
* type="string",
* ),
* )
* ),
* @OA\Response(
* response="404",
* ref="#/components/responses/404"
* ),
* @OA\Response(
* response="422",
* ref="#/components/responses/422"
* ),
* @OA\Response(
* response="200",
* description="OK",
* @OA\JsonContent(
* @OA\Property(
* property="ip",
* type="string",
* format="ip"
* ),
* @OA\Property(
* property="port",
* type="integer"
* ),
* @OA\Property(
* property="pubkey",
* type="string",
* pattern="^-----BEGIN PUBLIC KEY-----(\n|\r|\r\n)([0-9a-zA-Z\+\/=]{64}(\n|\r|\r\n))*([0-9a-zA-Z\+\/=]{1,63}(\n|\r|\r\n))?-----END PUBLIC KEY-----$"
* ),
* )
* ),
* security={{"jwt":{}}},
* )
*/
public function connect(ConnectRequest $request, $id)
{
$user = User::findOrFail(Auth::guard('client')->id());
if ($user->server_state == 'connected') {
if ($user->server_id != null) {
if ($user->server->online) {
return response()->json([
'message' => 'Client is already connected',
], 403);
}
}
$user->disconnect();
}
$server = Server::findOrFail($id);
if (!$server->online) {
return response()->json([
'message' => 'Server is offline',
], 403);
}
$user->connecting($server, $request->input('token'));
return response()->json([
"ip" => $server->ip,
"port" => $server->port,
"pubkey" => $server->pubkey
]);
}
}
\ No newline at end of file
<?php
namespace App\Http\Controllers\Client;
use App\Http\Controllers\Controller;
use App\Http\Requests\UpdateProfileRequest;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
class ProfileController extends Controller
{
/**
* @OA\Get(
* tags={"Clients:Authentication"},
* path="/auth/profile",
* summary="Get user profile",
* @OA\Response(
* response="401",
* ref="#/components/responses/401"
* ),
* @OA\Response(
* response="200",
* description="OK",
* @OA\JsonContent(
* @OA\Property(
* property="user",
* allOf={
* @OA\Schema(ref="#/components/schemas/User"),
* @OA\Schema(
* @OA\Property(
* property="server",
* allOf={
* @OA\Schema(ref="#/components/schemas/Server"),
* @OA\Schema(nullable=true)
* }
* ),
* @OA\Property(type="string", property="email", format="email"),
* )
* }
* ),
* ),
* ),
* security={{"jwt":{}}},
* )
*/
public function show()
{
return response()->json([
'user' => Auth::user()->load('server')->makeVisible('email'),
]);
}
/**
* @OA\Put(
* tags={"Clients:Authentication"},
* path="/auth/profile",
* summary="Update user profile",
* @OA\RequestBody(
* ref="#/components/requestBodies/UpdateProfile"
* ),
* @OA\Response(
* response="401",
* ref="#/components/responses/401"
* ),
* @OA\Response(
* response="422",
* ref="#/components/responses/422"
* ),
* @OA\Response(
* response="204",
* description="OK"
* ),
* security={{"jwt":{}}},
* )
*/
public function update(UpdateProfileRequest $request)
{
$data = $request->validated();
if (array_key_exists('password', $data))
$data['password'] = Hash::make($data['password']);
Auth::user()->update($data);
return response()->noContent();
}
/**
* @OA\Delete(
* tags={"Clients:Authentication"},
* path="/auth/profile",
* summary="Delete user profile",
* @OA\Response(
* response="401",
* ref="#/components/responses/401"
* ),
* @OA\Response(
* response="204",
* description="OK"
* ),
* security={{"jwt":{}}},
* )
*/
public function destroy()
{
$user = Auth::user();
Auth::logout();
$user->delete();
return response()->noContent();
}
}
<?php
namespace App\Http\Controllers;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
/**
* @OA\Info(
* version="1.1.0",
* title="BomberNyan API Documentation",
* description="API for BomberNyan",
* )
*
* @OA\Server(
* url="https://mai-projet-integrateur.u-strasbg.fr/vmProjetIntegrateurgrp7-0/api",
* description="API Server"
* )
*
* @OA\Server(
* url="http://localhost:8000/api",
* description="Local API Server"
* )
*
* @OA\Response(
* response="422",
* description="Missing field",
* @OA\JsonContent(
* @OA\Property(
* property="message",
* type="string",
* description="Description of the error",
* ),
* @OA\Property(
* property="errors",
* type="object",
* description="List of erronous fields",
* @OA\Property(
* @OA\Items(
* type="string",
* description="Description of the error"
* ),
* type="array",
* description="List of errors"
* ),
* ),
* ),
* )
*
* @OA\Response(
* response="401",
* description="Authentication error",
* @OA\JsonContent(
* @OA\Property(
* property="message",
* type="string"
* ),
* )
* )
*
* @OA\Response(
* response="403",
* description="Not Authorized",
* @OA\JsonContent(
* @OA\Property(
* property="message",
* type="string"
* ),
* )
* )
*
* @OA\Response(
* response="404",
* description="Not found",
* @OA\JsonContent(
* @OA\Property(
* property="message",
* type="string"
* ),
* )
* )
*/
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
}
<?php
namespace App\Http\Controllers\Server;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Http\Requests\AcceptRequest;
use Illuminate\Support\Facades\Auth;
class AcceptController extends Controller
{
/**
* @OA\Post(
* tags={"Servers:User"},
* path="/user/{id}/accept",
* summary="Accept a user's connection",
* @OA\Parameter(
* name="id",
* in="path",
* required=true,
* @OA\Schema(type="integer")
* ),
* @OA\RequestBody(
* ref="#/components/requestBodies/Accept"
* ),
* @OA\Response(
* response="401",
* ref="#/components/responses/401"
* ),
* @OA\Response(
* response="403",
* description="Forbidden",
* @OA\JsonContent(
* @OA\Property(
* property="message",
* type="string",
* ),
* )
* ),
* @OA\Response(
* response="404",
* ref="#/components/responses/404"
* ),
* @OA\Response(
* response="422",
* ref="#/components/responses/422"
* ),
* @OA\Response(
* response="200",
* description="OK",
* @OA\JsonContent(
* @OA\Property(
* property="user",
* ref="#/components/schemas/User"
* ),
* ),
* ),
* security={{"server-jwt":{}}},
* )
*/
public function accept(AcceptRequest $request, $id) {
$server = Auth::guard('server')->user();
$user = User::findOrFail($id);
if ($user->server_state != 'connecting' || $user->server_token != $request->input('token') || $user->server_id != $server->id) {
return response()->json([
'message' => 'Wrong token',
], 403);
}
$user->connect($server);
return response()->json([
"user" => $user
], 200);
}
}
<?php
namespace App\Http\Controllers\Server;
use App\Http\Controllers\Controller;
use App\Http\Requests\ServerHeartbeatRequest;
use App\Http\Requests\ServerLoginRequest;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class AuthController extends Controller
{
/**
* @OA\Post(
* tags={"Servers:Authentication"},
* path="/auth/server/login",
* summary="Login to the API",
* @OA\RequestBody(
* ref="#/components/requestBodies/ServerLogin"
* ),
* @OA\Response(
* response="401",
* ref="#/components/responses/401"
* ),
* @OA\Response(
* response="422",
* ref="#/components/responses/422"
* ),
* @OA\Response(
* response="200",
* description="OK",
* @OA\JsonContent(
* @OA\Property(
* property="token",
* type="string",
* description="Token to use as Bearer token",
* ),
* @OA\Property(
* property="server",
* type="object",
* ref="#/components/schemas/Server"
* ),
* ),
* ),
* )
*/
public function login(ServerLoginRequest $request)
{
$token = Auth::guard('server')->attempt($request->validated());
if (!$token) {
return response()->json([
'message' => 'Unauthorized',
], 401);
}
$server = Auth::guard('server')->user();
return response()->json([
'server' => $server,
'token' => $token,
]);
}
/**
* @OA\Post(
* tags={"Servers:Authentication"},
* path="/auth/server/logout",
* summary="Logout of the API",
* @OA\Response(
* response="401",
* ref="#/components/responses/401"
* ),
* @OA\Response(
* response="204",
* description="OK",
* ),
* security={{"server-jwt":{}}},
* )
*/
public function logout()
{
Auth::guard('server')->logout();
return response()->noContent();
}
/**
* @OA\Post(
* tags={"Servers:Authentication"},
* path="/auth/server/refresh",
* summary="Refresh an API token",
* @OA\Response(
* response="401",
* ref="#/components/responses/401"
* ),
* @OA\Response(
* response="200",
* description="OK",
* @OA\JsonContent(
* @OA\Property(
* property="token",
* type="string",
* description="Token to use as Bearer token",
* ),
* @OA\Property(
* property="server",
* type="object",
* ref="#/components/schemas/Server"
* ),
* ),
* ),
* security={{"server-jwt":{}}},
* )
*/
public function refresh()
{
return response()->json([
'server' => Auth::guard('server')->user(),
'token' => Auth::guard('server')->refresh(),
]);
}
/**
* @OA\Get(
* tags={"Servers:Authentication"},
* path="/auth/server/profile",
* summary="Get server profile",
* @OA\Response(
* response="401",
* ref="#/components/responses/401"
* ),
* @OA\Response(
* response="200",
* description="OK",
* @OA\JsonContent(
* @OA\Property(
* property="server",
* ref="#/components/schemas/Server",
* ),
* ),
* ),
* security={{"server-jwt":{}}},
* )
*/
public function profile()
{
return response()->json([
'server' => Auth::user(),
]);
}
/**
* @OA\Post(
* tags={"Servers:Authentication"},
* path="/auth/server/heartbeat",
* summary="Singla to the API that the server is online",
* @OA\RequestBody(
* ref="#/components/requestBodies/ServerHeartbeat"
* ),
* @OA\Response(
* response="401",
* ref="#/components/responses/401"
* ),
* @OA\Response(
* response="422",
* ref="#/components/responses/422"
* ),
* @OA\Response(
* response="204",
* description="OK",
* ),
* )
*/
public function heartbeat(ServerHeartbeatRequest $request)
{
$server = Auth::guard('server')->user();
$server->heartbeat($request->input("ip"), $request->input("port"), $request->input("pubkey"));
return response()->noContent();
}
}
<?php
namespace App\Http\Controllers\Server;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Http\Requests\AcceptRequest;
use Illuminate\Support\Facades\Auth;
class DisconnectController extends Controller
{
/**
* @OA\Post(
* tags={"Servers:User"},
* path="/user/{id}/disconnect",
* summary="Disconnect an user",
* @OA\Parameter(
* name="id",
* in="path",
* required=true,
* @OA\Schema(type="integer")
* ),
* @OA\Response(
* response="401",
* ref="#/components/responses/401"
* ),
* @OA\Response(
* response="404",
* ref="#/components/responses/404"
* ),
* @OA\Response(
* response="403",
* description="Forbidden",
* @OA\JsonContent(
* @OA\Property(
* property="message",
* type="string",
* ),
* )
* ),
* @OA\Response(
* response="204",
* description="OK"
* ),
* security={{"server-jwt":{}}},
* )
*/
public function disconnect($id) {
$server = Auth::guard('server')->user();
$user = User::findOrFail($id);
if (!($user->server_id === $server->id && $user->server_state !== 'offline')) {
return response()->json([
'message' => 'User is not connected',
], 403);
}
$user->disconnect();
return response()->noContent();
}
}
<?php
namespace App\Http\Controllers\Shared;
use App\Http\Controllers\Controller;
use App\Http\Requests\CreateGameRequest;
use App\Http\Requests\UpdateGameRequest;
use App\Models\Game;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
class GameController extends Controller
{
/**
* @OA\Get(
* tags={"Clients:Game"},
* path="/game",
* summary="Get game list",
* @OA\Response(
* response="401",
* ref="#/components/responses/401"
* ),
* @OA\Response(
* response="200",
* description="OK",
* @OA\JsonContent(
* @OA\Property(
* property="games",
* type="array",
* @OA\Items(ref="#/components/schemas/Game")
* ),
* ),
* ),
* security={{"jwt":{}}},
* )
*/
public function index()
{
return response()->json([
"games" => Game::all()
]);
}
/**
* @OA\Get(
* tags={"Clients:Game"},
* path="/game/{id}",
* summary="Get a game",
* @OA\Parameter(
* name="id",
* in="path",
* required=true,
* @OA\Schema(type="integer")
* ),
* @OA\Response(
* response="401",
* ref="#/components/responses/401"
* ),
* @OA\Response(
* response="404",
* ref="#/components/responses/404"
* ),
* @OA\Response(
* response="200",
* description="OK",
* @OA\JsonContent(
* @OA\Property(
* property="game",
* allOf={
* @OA\Schema(ref="#/components/schemas/Game"),
* @OA\Schema(
* @OA\Property(
* property="server",
* allOf={
* @OA\Schema(ref="#/components/schemas/Server"),
* @OA\Schema(nullable=true)
* }
* ),
* )
* }
* ),
* ),
* ),
* security={{"jwt":{}}},
* )
*/
public function show($id)
{
return response()->json([
"game" => Game::findOrFail($id)->load("server")
]);
}
/**
* @OA\Get(
* tags={"Clients:Game"},
* path="/game/{id}/user",
* summary="Get users from a game",
* @OA\Parameter(
* name="id",
* in="path",
* required=true,
* @OA\Schema(type="integer")
* ),
* @OA\Response(
* response="401",
* ref="#/components/responses/401"
* ),
* @OA\Response(
* response="404",
* ref="#/components/responses/404"
* ),
* @OA\Response(
* response="200",
* description="OK",
* @OA\JsonContent(
* @OA\Property(
* property="users",
* type="array",
* @OA\Items(
* allOf={
* @OA\Schema(ref="#/components/schemas/User"),
* @OA\Schema(ref="#/components/schemas/UserGame")
* }
* )
* ),
* ),
* ),
* security={{"jwt":{}}},
* )
*/
public function index_users($id)
{
return response()->json([
"users" => Game::findOrFail($id)->users
]);
}
/**
* @OA\Get(
* tags={"Clients:Game"},
* path="/game/{id}/user/{user_id}",
* summary="Get a user from a game",
* @OA\Parameter(
* name="id",
* in="path",
* required=true,
* @OA\Schema(type="integer")
* ),
* @OA\Parameter(
* name="user_id",
* in="path",
* required=true,
* @OA\Schema(type="integer")
* ),
* @OA\Response(
* response="401",
* ref="#/components/responses/401"
* ),
* @OA\Response(
* response="404",
* ref="#/components/responses/404"
* ),
* @OA\Response(
* response="200",
* description="OK",
* @OA\JsonContent(
* @OA\Property(
* property="user",
* allOf={
* @OA\Schema(ref="#/components/schemas/User"),
* @OA\Schema(ref="#/components/schemas/UserGame")
* }
* ),
* ),
* ),
* security={{"jwt":{}}},
* )
*/
public function show_users($id, $user_id)
{
return response()->json([
"user" => Game::findOrFail($id)->users()->findOrFail($user_id)
]);
}
/**
* @OA\Post(
* tags={"Servers:Game"},
* path="/game",
* summary="Create a game",
* @OA\RequestBody(
* ref="#/components/requestBodies/CreateGame"
* ),
* @OA\Response(
* response="401",
* ref="#/components/responses/401"
* ),
* @OA\Response(
* response="403",
* ref="#/components/responses/403"
* ),
* @OA\Response(
* response="422",
* ref="#/components/responses/422"
* ),
* @OA\Response(
* response="201",
* description="Resource created",
* @OA\JsonContent(
* @OA\Property(
* property="game",
* ref="#/components/schemas/Game",
* ),
* ),
* ),
* security={{"server-jwt":{}}},
* )
*/
public function store(CreateGameRequest $request)
{
$server = Auth::guard('server')->user();
DB::beginTransaction();
$game = Game::create([
"server_id" => $server->id
]);
foreach ($request->input("users") as $user) {
$user = User::findOrFail($user["id"]);
if ($user->server_id === $server->id && $user->server_state === 'connected') {
$game->users()->attach($user->id, []);
} else {
DB::rollBack();
return response()->json([
"message" => "Forbidden access to user " . $user->id
], 403);
}
}
DB::commit();
return response()->json([
"game" => $game
], 201);
}
/**
* @OA\Put(
* tags={"Servers:Game"},
* path="/game/{id}",
* summary="Update a game",
* @OA\Parameter(
* name="id",
* in="path",
* required=true,
* @OA\Schema(type="integer")
* ),
* @OA\RequestBody(
* ref="#/components/requestBodies/UpdateGame"
* ),
* @OA\Response(
* response="401",
* ref="#/components/responses/401"
* ),
* @OA\Response(
* response="403",
* ref="#/components/responses/403"
* ),
* @OA\Response(
* response="404",
* ref="#/components/responses/404"
* ),
* @OA\Response(
* response="422",
* ref="#/components/responses/422"
* ),
* @OA\Response(
* response="200",
* description="Resource updated",
* @OA\JsonContent(
* @OA\Property(
* property="game",
* ref="#/components/schemas/Game",
* ),
* ),
* ),
* security={{"server-jwt":{}}},
* )
*/
public function update(UpdateGameRequest $request, $id)
{
$server = Auth::guard('server')->user();
$game = Game::findOrFail($id);
if ($game->server_id !== $server->id)
{
abort(404);
}
if ($game->state === 'created' && $request->input('state') === 'playing')
{
$game->start();
return response()->json([
"game" => $game
], 200);
}
if ($game->state === 'playing' && $request->input('state') === 'finished')
{
$game->end($request->input('users'));
return response()->json([
"game" => $game
], 200);
}
return response()->json([
"message" => "Invalid state."
], 403);
}
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment