Add more API resources; user bid management and tests #35 #36

This commit is contained in:
Nabeel Shahzad
2017-12-12 16:58:27 -06:00
parent 5b25a464ba
commit 248a8d1488
27 changed files with 470 additions and 166 deletions

View File

@@ -6,12 +6,21 @@ use \Illuminate\Support\Facades\Facade;
class Utils extends Facade
{
protected static function getFacadeAccessor()
{
return 'utils';
}
/**
* Returns a 40 character API key that a user can use
* @return string
*/
public static function generateApiKey()
{
$key = sha1(time() . mt_rand());
return $key;
}
/**
* Convert seconds to an array of hours, minutes, seconds
* @param $seconds

View File

@@ -2,6 +2,7 @@
namespace App\Http\Controllers\Api;
use Log;
use Illuminate\Http\Request;
use App\Http\Controllers\AppBaseController;
@@ -25,6 +26,10 @@ class FlightController extends AppBaseController
return new FlightResource($flight);
}
/**
* @param Request $request
* @return mixed
*/
public function search(Request $request)
{
try {

View File

@@ -0,0 +1,55 @@
<?php
namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\AppBaseController;
use App\Repositories\UserRepository;
use App\Models\UserBid;
use App\Http\Resources\Flight as FlightResource;
use App\Http\Resources\User as UserResource;
use App\Http\Resources\UserBid as UserBidResource;
class UserController extends AppBaseController
{
protected $userRepo;
public function __construct(UserRepository $userRepo)
{
$this->userRepo = $userRepo;
}
/**
* Return the profile for the currently auth'd user
*/
public function index(Request $request)
{
UserResource::withoutWrapping();
return new UserResource($request->user);
}
/**
* Get the profile for the passed-in user
*/
public function get($id)
{
UserResource::withoutWrapping();
return new UserResource($this->userRepo->find($id));
}
/**
* Return all of the bids for the passed-in user
*/
public function bids($id)
{
$flights = UserBid::where(['user_id' => $id])->get()
->pluck('flight');
return FlightResource::collection($flights);
}
}

View File

@@ -6,7 +6,6 @@
namespace App\Http\Middleware;
use Auth;
use Cache;
use Closure;
use App\Models\User;
@@ -28,16 +27,8 @@ class ApiAuth
// Try to find the user via API key. Cache this lookup
$api_key = $request->header('Authorization');
$user = User::where('apikey', $api_key)->first();
/*$user = Cache::remember(
config('cache.keys.USER_API_KEY.key') . $api_key,
config('cache.keys.USER_API_KEY.time'),
function () use ($api_key) {
return User::where('apikey', $api_key)->first();
}
);*/
if(!$user) {
$user = User::where('api_key', $api_key)->first();
if($user === null) {
return $this->unauthorized();
}

View File

@@ -0,0 +1,13 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class Aircraft extends Resource
{
public function toArray($request)
{
return parent::toArray($request);
}
}

View File

@@ -0,0 +1,23 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class Airline extends Resource
{
public function toArray($request)
{
return [
'id' => $this->id,
'icao' => $this->icao,
'iata' => $this->iata,
'name' => $this->name,
'country' => $this->country,
'logo' => $this->logo,
#'active' => $this->active,
#'created_at' => $this->created_at,
#'updated_at' => $this->updated_at,
];
}
}

View File

@@ -6,12 +6,6 @@ use Illuminate\Http\Resources\Json\Resource;
class Airport extends Resource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return parent::toArray($request);

View File

@@ -6,12 +6,6 @@ use Illuminate\Http\Resources\Json\Resource;
class Flight extends Resource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
@@ -29,8 +23,10 @@ class Flight extends Resource
'flight_time' => $this->flight_time,
'notes' => $this->notes,
'active' => $this->active,
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
'subfleet' => Subfleet::collection($this->subfleets),
#'created_at' => $this->created_at,
#'updated_at' => $this->updated_at,
];
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class Rank extends Resource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'name' => $this->name,
#'auto_approve_acars' => $this->auto_approve_acars,
#'auto_approve_manual' => $this->auto_approve_manual,
#'auto_promote' => $this->auto_promote,
#'created_at' => $this->created_at,
#'updated_at' => $this->updated_at,
];
}
}

View File

@@ -0,0 +1,24 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class Subfleet extends Resource
{
public function toArray($request)
{
return [
'id' => $this->id,
'airline_id' => $this->airline_id,
'name' => $this->name,
'type' => $this->type,
'fuel_type' => $this->fuel_type,
'cargo_capacity' => $this->cargo_capacity,
'fuel_capacity' => $this->fuel_capacity,
'gross_weight' => $this->gross_weight,
'aircraft' => Aircraft::collection($this->aircraft),
];
}
}

View File

@@ -0,0 +1,31 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class User extends Resource
{
public function toArray($request)
{
return [
'id' => $this->id,
'name' => $this->name,
'email' => $this->email,
'apikey' => $this->apikey,
'rank_id' => $this->rank_id,
'home_airport' => $this->home_airport_id,
'curr_airport' => $this->curr_airport_id,
'last_pirep_id' => $this->last_pirep_id,
'flights' => $this->flight,
'flight_time' => $this->flight_time,
'balance' => $this->balance,
'timezone' => $this->timezone,
'active' => $this->active,
'airline' => Airline::make($this->airline),
'bids' => UserBid::collection($this->bids),
'rank' => Rank::make($this->rank),
];
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class UserBid extends Resource
{
public function toArray($request)
{
return [
'id' => $this->id,
'user_id' => $this->user_id,
'flight_id' => $this->flight_id,
'flight' => Flight::collection($this->whenLoaded('flight'))
#'created_at' => $this->created_at,
#'updated_at' => $this->updated_at,
];
}
}

View File

@@ -4,51 +4,38 @@ namespace App\Models;
use Eloquent as Model;
/**
* Class Aircraft
*
* @package App\Models
* @version June 9, 2017, 1:06 am UTC
*/
class Aircraft extends Model
{
public $table = 'aircraft';
protected $dates = ['deleted_at'];
public $fillable
= [
'subfleet_id',
'airport_id',
'name',
'registration',
'tail_number',
'active',
];
public $fillable = [
'subfleet_id',
'airport_id',
'name',
'registration',
'tail_number',
'active',
];
/**
* The attributes that should be casted to native types.
*
* @var array
*/
protected $casts
= [
'subfleet_id' => 'string',
'name' => 'string',
'registration' => 'string',
'active' => 'boolean',
];
protected $casts = [
'active' => 'boolean',
];
/**
* Validation rules
*
* @var array
*/
public static $rules
= [
'name' => 'required',
'active' => '',
];
public static $rules = [
'name' => 'required',
];
/**
* foreign keys

View File

@@ -6,11 +6,6 @@ use Eloquent as Model;
use App\Models\Traits\HashId;
/**
* Class Flight
*
* @package App\Models
*/
class Flight extends Model
{
use HashId;
@@ -64,6 +59,11 @@ class Flight extends Model
'arr_airport_id' => 'required',
];
public function getFlightIdIataAttribute($value)
{
}
/**
* Relationship
*/

View File

@@ -33,6 +33,11 @@ class Subfleet extends Model
'gross_weight' => 'double',
];
public function aircraft()
{
return $this->hasMany('App\Models\Aircraft', 'subfleet_id');
}
public function airline()
{
return $this->belongsTo('App\Models\Airline', 'airline_id');

View File

@@ -9,69 +9,41 @@ use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Contracts\Auth\CanResetPassword;
/**
* App\User
*
* @property integer
* $id
* @property string
* $name
* @property string
* $email
* @property string
* $password
* @property string
* $remember_token
* @property \Carbon\Carbon
* $created_at
* @property \Carbon\Carbon
* $updated_at
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection|\Illuminate\Notifications\DatabaseNotification[]
* $notifications
* @property-read \Illuminate\Notifications\DatabaseNotificationCollection|\Illuminate\Notifications\DatabaseNotification[]
* $unreadNotifications
* @method static \Illuminate\Database\Query\Builder|\App\Models\User
* whereId($value)
* @method static \Illuminate\Database\Query\Builder|\App\Models\User
* whereName($value)
* @method static \Illuminate\Database\Query\Builder|\App\Models\User
* whereEmail($value)
* @method static \Illuminate\Database\Query\Builder|\App\Models\User
* wherePassword($value)
* @method static \Illuminate\Database\Query\Builder|\App\Models\User
* whereRememberToken($value)
* @method static \Illuminate\Database\Query\Builder|\App\Models\User
* whereCreatedAt($value)
* @method static \Illuminate\Database\Query\Builder|\App\Models\User
* whereUpdatedAt($value)
* @mixin \Eloquent
* @property integer $id
* @property string $name
* @property string $email
* @property string $password
* @property string $api_key
* @property string $flights
* @property string $flight_time
* @property string $remember_token
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @mixin \Illuminate\Notifications\Notifiable
* @mixin \Zizaco\Entrust\Traits\EntrustUserTrait
*/
class User extends Authenticatable
{
use Notifiable;
use EntrustUserTrait;
//use SoftDeletes;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable
= [
'name',
'email',
'password',
'airline_id',
'home_airport_id',
'curr_airport_id',
'rank_id',
'timezone',
'active',
];
public $table = 'users';
protected $fillable = [
'name',
'email',
'password',
'airline_id',
'home_airport_id',
'curr_airport_id',
'rank_id',
'timezone',
'active',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password',
@@ -84,32 +56,13 @@ class User extends Authenticatable
'balance' => 'double',
];
/**
* Validation rules
*
* @var array
*/
public static $rules = [
];
/**
* Returns a 40 character API key that a user can use
* @return string
*/
public static function generateApiKey()
{
$key = sha1(time() . mt_rand());
return $key;
}
public function getPilotIdAttribute($value)
{
$length = setting('pilots.id_length');
return $this->airline->icao . str_pad($this->id, $length, '0', STR_PAD_LEFT);
}
public function gravatar()
public function getGravatarAttribute($value)
{
$size = 80;
$default = 'https://en.gravatar.com/userimage/12856995/7c7c1da6387853fea65ff74983055386.png';
@@ -136,7 +89,7 @@ class User extends Authenticatable
return $this->belongsTo('App\Models\Airport', 'curr_airport_id');
}
public function flights()
public function bids()
{
return $this->hasMany('App\Models\UserBid', 'user_id');
}

View File

@@ -0,0 +1,79 @@
<?php
/**
* Created by IntelliJ IDEA.
* User: nshahzad
* Date: 12/12/17
* Time: 2:48 PM
*/
namespace App\Services;
use Log;
use App\Models\Flight;
use App\Models\User;
use App\Models\UserBid;
class FlightService extends BaseService
{
/**
* Allow a user to bid on a flight. Check settings and all that good stuff
* @param Flight $flight
* @param User $user
* @return UserBid
*/
public function addBid(Flight $flight, User $user): UserBid
{
# If it's already been bid on, then it can't be bid on again
if($flight->has_bid && setting('bids.disable_flight_on_bid')) {
Log.info($flight->id . ' already has a bid, skipping');
return null;
}
# See if we're allowed to have multiple bids or not
if(!setting('bids.allow_multiple_bids')) {
$user_bids = UserBid::where(['user_id' => $user->id])->first();
if($user_bids) {
Log.info('User "' . $user->id . '" already has bids, skipping');
return null;
}
}
# See if this user has this flight bid on already
$bid_data = [
'user_id' => $user->id,
'flight_id' => $flight->id
];
$user_bid = UserBid::where($bid_data)->first();
if($user_bid) {
return $user_bid;
}
$user_bid = UserBid::create($bid_data);
$flight->has_bid = true;
$flight->save();
return $user_bid;
}
/**
* Remove a bid from a given flight
* @param Flight $flight
* @param User $user
* @throws Exception
*/
public function removeBid(Flight $flight, User $user)
{
$user_bid = UserBid::where([
'flight_id' => $flight->id, 'user_id' => $user->id
])->first();
if($user_bid) {
$user_bid->forceDelete();
}
$flight->has_bid = false;
$flight->save();
}
}

View File

@@ -3,6 +3,7 @@
namespace App\Services;
use App\Events\UserRegistered;
use App\Facades\Utils;
use App\Models\User;
use App\Models\Rank;
use App\Models\Role;
@@ -15,32 +16,32 @@ use Illuminate\Support\Facades\Hash;
class UserService extends BaseService
{
public function adjustFlightCount(User &$pilot, int $count): User
public function adjustFlightCount(User $user, int $count): User
{
$pilot->refresh();
$pilot->flights = $pilot->flights + $count;
$pilot->save();
$user->refresh();
$user->flights += $count;
$user->save();
event(new UserStateChanged($pilot));
event(new UserStateChanged($user));
return $pilot;
return $user;
}
public function adjustFlightHours(User &$pilot, int $hours): User
public function adjustFlightHours(User $user, int $hours): User
{
$pilot->refresh();
$pilot->flight_time = $pilot->flight_time + $hours;
$pilot->save();
$user->refresh();
$user->flight_time += $hours;
$user->save();
event(new UserStateChanged($pilot));
event(new UserStateChanged($user));
return $pilot;
return $user;
}
public function calculatePilotRank(User &$pilot): User
public function calculatePilotRank(User $user): User
{
$pilot->refresh();
$pilot_hours = $pilot->flight_time / 3600;
$user->refresh();
$pilot_hours = $user->flight_time / 3600;
# TODO: Cache
$ranks = Cache::remember(
@@ -54,23 +55,28 @@ class UserService extends BaseService
if($rank->hours > $pilot_hours) {
break;
} else {
$pilot->rank_id = $rank->id;
$user->rank_id = $rank->id;
}
}
$pilot->save();
$user->save();
event(new UserStateChanged($pilot));
event(new UserStateChanged($user));
return $pilot;
return $user;
}
/**
* Register a pilot
* @param array $data
* @return mixed
*/
public function createPilot(array $data)
{
$user = User::create([
'name' => $data['name'],
'email' => $data['email'],
'apikey' => User::generateApiKey(),
'api_key' => Utils::generateApiKey(),
'airline_id' => $data['airline'],
'home_airport_id' => $data['home_airport'],
'curr_airport_id' => $data['home_airport'],