Commit 09f9dfb7 authored by hangjun83's avatar hangjun83

后端框架初始化提交

parent 5a844386
#标准树(有三种不同的树:未注册的树x主要用于本地或私有环境,个人树prs主要用于非商业发行的项目,供应商树vndvnd主要用于可公开获得和分发的项目。您使用的标准树将取决于您正在开发的项目。)
API_STANDARDS_TREE=x
#亚型(子类型通常是应用程序或项目的缩写全为小写。)
API_SUBTYPE=rhawn
#前缀
API_PREFIX=/
#域(也就是项目网址)
API_DOMAIN=localhost
#默认API版本
API_VERSION=v1
#API名称
API_NAME="rhawn tools"
#条件请求状态(默认情况下,条件请求处于启用状态,因为它将在可能的情况下利用客户端缓存功能来缓存API请求。
API_CONDITIONAL_REQUEST=false
#严格模式(严格模式将要求客户端发送Accept标头,而不是默认使用配置文件中指定的版本。这意味着您将无法通过Web浏览器浏览API。如果启用了严格模式并且使用了无效的Accept头,
#那么API将抛出未处理的内容Symfony\Component\HttpKernel\Exception\BadRequestHttpException,您应该适当地对其进行处理。)
API_STRICT=true
#默认响应格式
API_DEFAULT_FORMAT=json
#调试模式
API_DEBUG=true
# lumen 配置文件
APP_NAME=Lumen
APP_ENV=local
APP_KEY=
APP_DEBUG=true
APP_URL=http://localhost
APP_TIMEZONE=UTC
APP_LOCALE=en
LOG_CHANNEL=stack
LOG_SLACK_WEBHOOK_URL=
LOG_QUERY=false
LOG_REQUEST=false
# 数据库配置
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=rhawn_tools
DB_USERNAME=root
DB_PASSWORD=123456
#MONGODB_HOST=127.0.0.1
#MONGODB_PORT=27017
#MONGODB_USERNAME=homestead
#MONGODB_PASSWORD=secret
#MONGODB_DATABASE=homestead
#MONGODB_AUTHENTICATION_DATABASE=admin
CACHE_DRIVER=file
QUEUE_CONNECTION=sync
JWT_SECRET=
MIT License
Copyright (c) 2020 Jiannei
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
This diff is collapsed.
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Console;
use Illuminate\Console\Scheduling\Schedule;
use Laravel\Lumen\Console\Kernel as ConsoleKernel;
class Kernel extends ConsoleKernel
{
/**
* The Artisan commands provided by your application.
*
* @var array
*/
protected $commands = [
];
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
*/
protected function schedule(Schedule $schedule)
{
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Events;
use Illuminate\Queue\SerializesModels;
abstract class Event
{
use SerializesModels;
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Events;
class ExampleEvent extends Event
{
/**
* Create a new event instance.
*/
public function __construct()
{
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Exceptions;
use Exception;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Validation\ValidationException;
use Jiannei\Response\Laravel\Support\Traits\ExceptionTrait;
use Laravel\Lumen\Exceptions\Handler as ExceptionHandler;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Throwable;
class Handler extends ExceptionHandler
{
use ExceptionTrait;
/**
* A list of the exception types that should not be reported.
*
* @var array
*/
protected $dontReport = [
AuthorizationException::class,
HttpException::class,
ModelNotFoundException::class,
ValidationException::class,
HttpResponseException::class,
];
/**
* Report or log an exception.
*
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
*
* @param Throwable $exception
*
* @throws Exception
*/
public function report(Throwable $exception)
{
parent::report($exception);
}
/**
* Render an exception into an HTTP response.
*
* @param Request $request
* @param Throwable $exception
* @return Response|JsonResponse
*
* @throws Throwable
*/
public function render($request, Throwable $exception)
{
return parent::render($request, $exception);
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Http\Middleware;
use App\Repositories\Enums\ResponseCodeEnum;
use Closure;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Contracts\Auth\Factory as Auth;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use App\Support\Traits\Helpers;
class Authenticate
{
use Helpers;
/**
* The authentication guard factory instance.
*
* @var Auth
*/
protected $auth;
/**
* Create a new middleware instance.
*
* @param Auth $auth
*/
public function __construct(Auth $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* @param Request $request
* @param Closure $next
* @param string|null $guard
* @return mixed
*
* @throws AuthorizationException
*/
public function handle($request, Closure $next, $guard = null)
{
/**
* 如果路由是登出或者是修改密码的时候,需要对token进行处理,否则jwt处理时会出错
*/
if(Str::endsWith(strtolower((string) $request->getPathInfo()), 'logout') ||
Str::endsWith(strtolower((string) $request->getPathInfo()), 'resetpassword')
){
$token = trim(str_ireplace('bearer', '', $request->header('authorization')));
$decodeToken = $this->decodeToken($token);
if(empty($decodeToken) || (!is_array($decodeToken) && !$decodeToken['hash'])){
throw new UnauthorizedHttpException('JWTAuth', 'Unable to authenticate with invalid token.');
}
/*$chains = app('tymon.jwt.parser')->getChain();
$chains[0]->setHeaderName($decodeToken['hash']);
app('tymon.jwt.parser')->setChain($chains);*/
$request->headers->set('authorization','bearer'.$decodeToken['hash']);
}
return $next($request);
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\ResourceCollection;
class UserCollection extends ResourceCollection
{
public function toArray($request)
{
return $this->collection->map(function ($item) {
return [
'nickname' => $item->name,
'email' => $item->email,
];
})->all();
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class UserResource extends JsonResource
{
public function toArray($request)
{
return [
'nickname' => $this->name,
'email' => $this->email,
];
}
}
This diff is collapsed.
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Http\V1;
use Jiannei\Response\Laravel\Support\Facades\Response;
use Jiannei\Response\Laravel\Support\Traits\ExceptionTrait;
use Laravel\Lumen\Routing\Controller as BaseController;
abstract class Controller extends BaseController
{
use ExceptionTrait;
/**
* request 参数验证
* @param $request
* @param $message
* @return bool|\Illuminate\Http\JsonResponse
*/
protected function validateRequest($request, $message){
$validateArr = [];
collect($message)->map(function($value,$key) use (&$validateArr){
$keys = explode('.',$key);
$validateArr[$keys[0]] = $keys[1];
});
$validator = Validator($request->all(), $validateArr, $message);
if ($validator->fails()) {
foreach($validator->errors()->getMessages() as $error) {
return Response::fail($error[0]);
}
}
return true;
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Jobs;
class ExampleJob extends Job
{
/**
* Create a new job instance.
*/
public function __construct()
{
}
/**
* Execute the job.
*/
public function handle()
{
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
abstract class Job implements ShouldQueue
{
/*
|--------------------------------------------------------------------------
| Queueable Jobs
|--------------------------------------------------------------------------
|
| This job base class provides a central location to place any logic that
| is shared across all of your jobs. The trait included with the class
| provides access to the "queueOn" and "delay" queue helper methods.
|
*/
use InteractsWithQueue;
use Queueable;
use SerializesModels;
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Listeners;
use App\Events\ExampleEvent;
class ExampleListener
{
/**
* Create the event listener.
*/
public function __construct()
{
}
/**
* Handle the event.
*
* @param \App\Events\ExampleEvent $event
*/
public function handle(ExampleEvent $event)
{
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Observers;
use App\Repositories\Enums\CacheEnum;
use App\Repositories\Models\AdminUsers;
use Illuminate\Support\Facades\Cache;
class UserObserver
{
public function updated(AdminUsers $user)
{
Cache::forget(CacheEnum::getCacheKey(CacheEnum::AUTHORIZATION_USER));
}
public function deleted(AdminUsers $user)
{
Cache::forget(CacheEnum::getCacheKey(CacheEnum::AUTHORIZATION_USER));
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Policies;
use App\Repositories\Enums\PermissionEnum;
use App\Repositories\Models\Post;
use App\Repositories\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class PostPolicy
{
use HandlesAuthorization;
/**
* Determine whether the user can view any posts.
*
* @param User $user
* @return mixed
*/
public function viewAny(User $user)
{
if ($user->can(PermissionEnum::ROUTE_POSTS_VIEW_ANY()->name)) {
return true;
}
return false;
}
/**
* Determine whether the user can view the post.
*
* @param User|null $user
* @param Post $post
* @return mixed
*/
public function view(?User $user, Post $post)
{
if ($post->published) {
return true;
}
// visitors cannot view unpublished items
if ($user === null) {
return false;
}
// admin overrides published status
if ($user->can(PermissionEnum::ROUTE_POSTS_VIEW()->name)) {
return true;
}
// authors can view their own unpublished posts
return $user->isOwnerOf($post);
}
/**
* Determine whether the user can create posts.
*
* @param User $user
* @return mixed
*/
public function create(User $user)
{
if ($user->can(PermissionEnum::ROUTE_POSTS_CREATE()->name)) {
return true;
}
return false;
}
/**
* Determine whether the user can update the post.
*
* @param User $user
* @param Post $post
* @return mixed
*/
public function update(User $user, Post $post)
{
if ($user->isOwnerOf($post) || $user->can('edit all posts')) {
return true;
}
return false;
}
/**
* Determine whether the user can delete the post.
*
* @param User $user
* @param Post $post
* @return mixed
*/
public function delete(User $user, Post $post)
{
if ($user->isOwnerOf($post) || $user->can(PermissionEnum::ROUTE_POSTS_DELETE()->name)) {
return true;
}
return false;
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Providers;
use App\Observers\UserObserver;
use App\Repositories\Models\AdminUsers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register()
{
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
$this->registerObservers(); // 注册观察者
}
protected function registerObservers(): void
{
AdminUsers::observe(UserObserver::class);
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Providers\Auth;
use App\Repositories\Enums\CacheEnum;
use App\Support\Traits\Helpers;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Support\Str;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
class AdminUsersProvider implements UserProvider
{
use Helpers;
protected $model = null;
public function __construct($app, $model)
{
if(!$model instanceof \Illuminate\Database\Eloquent\Model){
$class = '\\'.ltrim($model, '\\');
$this->model = new $class;
}else{
$this->model = $model;
}
}
/**
* Retrieve a user by their unique identifier.
*
* @param mixed $identifier
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveById($identifier)
{
// 只做根据identifier的值做查询用户操作
$user = $this->model->newQuery()
->where($this->model->getAuthIdentifierName(), $identifier)
->first();
if($user->status === 0 ){
return throw new AuthenticationException('用户已被禁用,请联系管理员.');
}
return $user;
/*return Cache::remember($cacheKey, $cacheExpireTime, function () use ($identifier) {
return $this->model->newQuery()
->where($this->model->getAuthIdentifierName(), $identifier)
->first();
});*/
}
/**
* Retrieve a user by the given credentials.
*
* @param array $credentials
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveByCredentials(array $credentials)
{
if (empty($credentials)) {
return throw new UnauthorizedHttpException('auth params error','参数缺少',null,ResponseCodeEnum::CLIENT_PARAMETER_ERROR);
}
$query = $this->model->newQuery();
foreach ($credentials as $key => $value) {
if (Str::contains($key, 'password')) {
$value = $this->model->encryptPassword($value);
//continue;
}
if (is_array($value) || $value instanceof Arrayable) {
$query->whereIn($key, $value);
} else {
$query->where($key, $value);
}
}
return $query->first();
}
/**
* Validate a user against the given credentials.
*
* @param \Illuminate\Contracts\Auth\Authenticatable $user
* @param array $credentials
* @return bool
*/
public function validateCredentials(UserContract $user, array $credentials)
{
$encodePassword = $this->model->encryptPassword($credentials['password']);
if($encodePassword !== $user->password){
return throw new AuthenticationException('用户登陆密码错误,请重新输入.');
}
if($user->status === 0 ){
return throw new AuthenticationException('用户已被禁用,请联系管理员.');
}
return true;
}
/**
* Retrieve a user by their unique identifier and "remember me" token.
*
* @param mixed $identifier
* @param string $token
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveByToken($identifier, $token)
{
return null;
}
/**
* Update the "remember me" token for the given user in storage.
*
* @param \Illuminate\Contracts\Auth\Authenticatable $user
* @param string $token
* @return void
*/
public function updateRememberToken(UserContract $user, $token)
{
}
}
<?php
namespace App\Providers\Auth\Jwt;
use Dingo\Api\Auth\Provider\Authorization;
use Exception;
use Dingo\Api\Routing\Route;
use Illuminate\Http\Request;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use App\Repositories\Enums\ResponseCodeEnum;
use App\Support\Traits\Helpers ;
use Tymon\JWTAuth\JWTAuth;
class AdminAuthProvider extends Authorization
{
use Helpers;
/**
* The JWTAuth instance.
*
* @var \Tymon\JWTAuth\JWTAuth
*/
protected $auth;
public function __construct(JWTAuth $auth){
$this->auth = $auth;
}
/**
* Authenticate request with a JWT.
*
* @param \Illuminate\Http\Request $request
* @param \Dingo\Api\Routing\Route $route
* @return mixed
*/
public function authenticate(Request $request, Route $route)
{
try{
$token = $this->getToken($request);
$decodeToken = $this->decodeToken($token);
if(empty($decodeToken) || (!is_array($decodeToken) && !$decodeToken['hash'])){
throw new UnauthorizedHttpException('JWTAuth', 'Unable to authenticate with invalid token.');
}
if (! $user = $this->auth->setToken($decodeToken['hash'])->authenticate()) {
throw new UnauthorizedHttpException('JWTAuth', 'Unable to authenticate with invalid token.');
}
}catch(Exception $exception){
if($exception instanceof UnauthorizedHttpException){
throw $exception;
}
throw new UnauthorizedHttpException('AdminAuth', $exception->getMessage(),null, ResponseCodeEnum::CLIENT_PARAMETER_ERROR);
}
return $user;
}
/**
* Get the JWT from the request.
*
* @param \Illuminate\Http\Request $request
* @return string
*
* @throws \Exception
*/
protected function getToken(Request $request)
{
try {
$this->validateAuthorizationHeader($request);
$token = $this->parseAuthorizationHeader($request);
} catch (Exception $exception) {
if (! $token = $request->query('token', false)) {
throw $exception;
}
}
return $token;
}
/**
* Parse JWT from the authorization header.
*
* @param \Illuminate\Http\Request $request
* @return string
*/
protected function parseAuthorizationHeader(Request $request)
{
return trim(str_ireplace($this->getAuthorizationMethod(), '', $request->header('authorization')));
}
/**
* Get the providers authorization method.
*
* @return string
*/
public function getAuthorizationMethod()
{
return 'bearer';
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Providers;
use App\Repositories\Enums\PermissionEnum;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\ServiceProvider;
use App\Providers\Auth\AdminUsersProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* Boot the authentication services for the application.
*/
public function boot()
{
//Gate::before(PermissionEnum::gateBeforeCallback());
$this->app['auth']->provider('superadmin', function ($app, array $config) {
return new AdminUsersProvider($app, $config['model']);
});
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Providers;
use Prettus\Repository\Providers\LumenRepositoryServiceProvider;
class RepositoryServiceProvider extends LumenRepositoryServiceProvider
{
/**
* Bootstrap services.
*/
public function boot()
{
$this->app->bind(
\App\Repositories\Contracts\UsersRepository::class,
\App\Repositories\Eloquent\UsersRepositoryEloquent::class
);
$this->app->bind(
\App\Repositories\Contracts\MenusRepository::class,
\App\Repositories\Eloquent\MenusRepositoryEloquent::class
);
$this->app->bind(
\App\Repositories\Contracts\RolesRepository::class,
\App\Repositories\Eloquent\RolesRepositoryEloquent::class
);
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Contracts;
use Prettus\Repository\Contracts\RepositoryInterface;
/**
* Interface UserRepository.
*/
interface MenusRepository extends RepositoryInterface
{
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Contracts;
use Prettus\Repository\Contracts\RepositoryInterface;
/**
* Interface UserRepository.
*/
interface RolesRepository extends RepositoryInterface
{
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Contracts;
use Prettus\Repository\Contracts\RepositoryInterface;
/**
* Interface UserRepository.
*/
interface UsersRepository extends RepositoryInterface
{
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Criteria;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Prettus\Repository\Contracts\CriteriaInterface;
use Prettus\Repository\Contracts\RepositoryInterface;
abstract class Criteria implements CriteriaInterface
{
/**
* @var Request
*/
protected $request;
public function __construct(Request $request)
{
$this->request = $request;
}
public function apply($model, RepositoryInterface $repository)
{
$model = $this->before($model);
$model = $model->where(function ($query) {
/** @var Builder $query */
$this->condition($query);
});
return $this->after($model);
}
/**
* Splice the query according to the parameters in the request.
*
* @param Builder $query
*/
protected function condition(Builder $query): void
{
}
protected function before($model)
{
return $model;
}
protected function after($model)
{
return $model;
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Criteria;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use Prettus\Repository\Contracts\RepositoryInterface;
use Prettus\Repository\Criteria\RequestCriteria as BaseRequestCriteria;
class RequestCriteria extends BaseRequestCriteria
{
/**
* Apply criteria in query repository.
*
* @param Builder|Model $model
* @param RepositoryInterface $repository
* @return mixed
*
* @throws \Exception
*/
public function apply($model, RepositoryInterface $repository)
{
$cursor = $this->request->get(config('repository.criteria.params.cursor', 'cursor'));
if ($cursor) {
$keyType = $model->getKeyType();
$key = $model->getKeyName();
$cursor = in_array($keyType, ['int', 'integer']) ? (int) $cursor : $cursor;
$sortedBy = $this->request->get(config('repository.criteria.params.sortedBy', 'sortedBy'), 'asc');
$sortedBy = ! empty($sortedBy) ? Str::lower($sortedBy) : 'asc';
$model = ($sortedBy === 'asc') ? $model->where($key, '>', $cursor) : $model->where($key, '<', $cursor);
}
return parent::apply($model, $repository);
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Criteria;
use Illuminate\Database\Eloquent\Builder;
use App\Repositories\Criteria\Criteria;
class UserCriteria extends Criteria
{
protected function condition(Builder $query): void
{
if ($name = $this->request->get('name')) {
$query->where('name', '=', $name);
}
if ($email = $this->request->get('email')) {
$query->where('email', 'like', "%$email%");
}
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Eloquent;
use App\Repositories\Presenters\Presenter;
use Illuminate\Database\Eloquent\Builder;
use Prettus\Repository\Eloquent\BaseRepository as BaseRepositoryEloquent;
abstract class BaseRepository extends BaseRepositoryEloquent
{
/**
* @var Presenter
*/
protected $presenter;
/**
* Retrieve all data of repository, simple paginated.
*
* @param null|int $limit
* @param array $columns
* @return mixed
*/
public function cursorPaginate($current, $limit = null, $columns = ['*'])
{
$this->applyCriteria();
$this->applyScope();
$limit = is_null($limit) ? config('repository.pagination.limit', 15) : (int) $limit;
$results = $this->model->select($columns)->limit($limit)->get();
if ($this->model instanceof Builder) {
$primaryKey = $this->model->getModel()->getKeyName();
} else {
$primaryKey = $this->model->getKeyName();
}
$count = $results->count();
$next = $count === $limit ? optional($results->last())->{$primaryKey} : null;
$prev = request('prev');
$this->presenter->makeCursor((int) $current, $prev ? (int) $prev : '', $next, $count);
$this->resetModel();
return $this->parserResult($results);
}
}
<?php
namespace App\Repositories\Eloquent;
use App\Repositories\Contracts\MenusRepository;
use App\Repositories\Criteria\RequestCriteria;
use App\Repositories\Models\Menus;
use App\Repositories\Eloquent\BaseRepository;
use Prettus\Validator\Contracts\ValidatorInterface;
/**
* Class UserRepositoryEloquent.
*/
class MenusRepositoryEloquent extends BaseRepository implements MenusRepository
{
protected $fieldSearchable = [
'menu_name',
];
/**
* 定义validator的检索规则
* @var \string[][]
*/
public $rules = [
ValidatorInterface::RULE_CREATE => [
'menu_name' => 'required',
'menu_path' => 'required',
'parent_id' => 'required',
'menu_type' => 'required',
'status' => 'required',
'sort' => 'required',
'is_show' => 'required',
'sys_default' => 'required'
],
ValidatorInterface::RULE_UPDATE => [
'menu_name' => 'required',
'menu_path' => 'required',
'parent_id' => 'required',
'menu_type' => 'required',
'status' => 'required',
'sort' => 'required',
'is_show' => 'required',
'sys_default' => 'required'
]
];
/**
* Specify Model class name.
*
* @return string
*/
public function model()
{
return Menus::class;
}
/**
* Boot up the repository, pushing criteria.
*
* @throws \Prettus\Repository\Exceptions\RepositoryException
*/
public function boot()
{
$this->pushCriteria(app(RequestCriteria::class));
}
}
<?php
namespace App\Repositories\Eloquent;
use App\Repositories\Contracts\RolesRepository;
use App\Repositories\Criteria\RequestCriteria;
use App\Repositories\Eloquent\BaseRepository;
use Prettus\Validator\Contracts\ValidatorInterface;
use Spatie\Permission\Models\Role;
/**
* Class UserRepositoryEloquent.
*/
class RolesRepositoryEloquent extends BaseRepository implements RolesRepository
{
protected $fieldSearchable = [
'name',
];
/**
* 定义validator的检索规则
* @var \string[][]
*/
public $rules = [
ValidatorInterface::RULE_CREATE => [
'name' => 'required',
],
ValidatorInterface::RULE_UPDATE => [
'name' => 'required',
]
];
/**
* Specify Model class name.
*
* @return string
*/
public function model()
{
return Role::class;
}
/**
* Boot up the repository, pushing criteria.
*
* @throws \Prettus\Repository\Exceptions\RepositoryException
*/
public function boot()
{
$this->pushCriteria(app(RequestCriteria::class));
}
/**
* @param $params
* @return \Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Eloquent\Model
*/
public function saveRole($params)
{
$saveParams = [
'name' => $params['name'],
'remark' => $params['remark'],
'guard_name' => config('auth.defaults.guard'),
];
if(isset($params['id'])){
$saveParams['updated_at'] = date('Y-m-d H:i:s',time());
//$saveParams['id'] = $params['id'];
$result = Role::query()->updateOrCreate(['id' => $params['id']],$saveParams);
}else{
$saveParams['created_at'] = date('Y-m-d H:i:s',time());
$saveParams['updated_at'] = date('Y-m-d H:i:s',time());
$result = Role::create($saveParams);
}
return $result;
}
}
<?php
namespace App\Repositories\Eloquent;
use App\Repositories\Contracts\UsersRepository;
use App\Repositories\Criteria\RequestCriteria;
use App\Repositories\Models\AdminUsers;
use App\Repositories\Validators\UserValidator;
use App\Repositories\Eloquent\BaseRepository;
use App\Support\Traits\Helpers;
use Prettus\Validator\Contracts\ValidatorInterface;
/**
* Class UserRepositoryEloquent.
*/
class UsersRepositoryEloquent extends BaseRepository implements UsersRepository
{
use Helpers;
protected $fieldSearchable = [
'username','email',
];
/**
* 定义validator的检索规则
* @var \string[][]
*/
public $rules = [
ValidatorInterface::RULE_CREATE => [
'username' => 'required|string',
'nickname' => 'required|string',
'password' => 'required|string|min:6',
'email' => 'required',
'token' => 'required',
'is_admin' => 'required',
'status' => 'required'
],
ValidatorInterface::RULE_UPDATE => [
'id' => 'required',
'nickname' => 'required|string',
'email' => 'required',
]
];
/**
* Specify Model class name.
*
* @return string
*/
public function model()
{
return AdminUsers::class;
}
/**
* Boot up the repository, pushing criteria.
*
* @throws \Prettus\Repository\Exceptions\RepositoryException
*/
public function boot()
{
$this->pushCriteria(app(RequestCriteria::class));
}
public function createOrUpdateUser($params)
{
$saveParams = $params;
if(isset($saveParams['id']) && !empty($saveParams['id'])){
$saveParams['updated_at'] = date('Y-m-d H:i:s',time());
unset($saveParams['is_admin']);
unset($saveParams['token']);
unset($saveParams['username']);
unset($saveParams['status']);
return $this->update($saveParams,$saveParams['id']);
}else{
$saveParams['is_admin'] = 0;
$saveParams['status'] = 1;
$saveParams['token'] = $this->randomFromDevice(16);
$saveParams['password'] = $this->encryptPassword($saveParams['password']);
$saveParams['lastlogin'] = 0;
$saveParams['created_at'] = date('Y-m-d H:i:s',time());
$saveParams['updated_at'] = date('Y-m-d H:i:s',time());
return $this->create($saveParams);
}
}
public function updateUserStatus($id, $status)
{
if($id){
$saveParams = [];
$saveParams['status'] = $status;
$saveParams['id'] = $id;
$user = $this->where('id',$id)->first()->toArray();
collect($this->rules['update'])->map(function($rule,$key) use ($user,&$saveParams){
if(isset($user[$key]) && !empty($user[$key])){
$saveParams[$key] = $user[$key];
}
});
$saveParams['status'] = $status;
$saveParams['id'] = $id;
$saveParams['updated_at'] = date('Y-m-d H:i:s',time());
return $this->update($saveParams,$id);
}
return true;
}
public function deleteUser($ids)
{
$users = $this->whereIn('id',$ids)->get();
if($users){
collect($users)->map(function($user){
$user->delete();
});
}
return true;
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Enums;
use Illuminate\Support\Carbon;
use Jiannei\Enum\Laravel\Repositories\Enums\CacheEnum as BaseCacheEnum;
class CacheEnum extends BaseCacheEnum
{
const AUTHORIZATION_USER = 'authorizationUser';
protected static function authorizationUser($options)
{
$exp = auth('api')->payload()->get('exp'); // token 剩余有效时间
return Carbon::now()->diffInSeconds(Carbon::createFromTimestamp($exp));
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Enums;
use Jiannei\Enum\Laravel\Repositories\Enums\LogEnum as BaseLogEnum;
class LogEnum extends BaseLogEnum
{
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Enums;
use Closure;
use Illuminate\Support\Str;
use Jiannei\Enum\Laravel\Contracts\LocalizedEnumContract;
use Jiannei\Enum\Laravel\Enum;
class PermissionEnum extends Enum implements LocalizedEnumContract
{
// 系统级别内置的权限:不允许分配权限给普通用户;(比如,只能超级管理员才能拥有)
const SYSTEM = '000000';
const SYSTEM_ACTIVITY_LOG_CLEAN = '000001';
const SYSTEM_CACHE_CLEAR = '000002';
// 路由级别权限:路由分组、路由操作;允许分配权限给普通用户,或分配给角色;ROUTE 开头
// 定义规范:viewAny、view、create、update、delete...
// https://learnku.com/docs/laravel/8.x/authorization/9382#f98610
const ROUTE = '100000';
const ROUTE_USERS = '100100';
const ROUTE_USERS_CREATE = '100110';
const ROUTE_USERS_DELETE = '100111';
const ROUTE_USERS_UPDATE = '100112';
const ROUTE_USERS_VIEW = '100113';
const ROUTE_USERS_VIEW_ANY = '100114';
const ROUTE_POSTS = '100200';
const ROUTE_POSTS_CREATE = '100210';
const ROUTE_POSTS_DELETE = '100211';
const ROUTE_POSTS_UPDATE = '100212';
const ROUTE_POSTS_VIEW = '100213';
const ROUTE_POSTS_VIEW_ANY = '100214';
// 数据级别权限:数据表权限,数据行权限,数据列权限
const DATA = '200000';
const DATA_USERS = '200100';
const DATA_USERS_ROW = '200101';
const DATA_USERS_COLUMN_EMAIL = '200110';
const DATA_POSTS = '200200';
const DATA_POSTS_ROW = '200201';
const DATA_POSTS_BODY = '200210';
public $name;
public $code;
public $type;
public $description;
public function __construct($enumValue, bool $strict = true)
{
parent::__construct($enumValue, $strict);
$this->name = Str::lower(str_replace('_', ':', $this->key));
$this->code = $enumValue;
$this->type = Str::lower(current(explode('_', $this->key)));
}
/**
* 根据常量定义构建权限.
*
* @return array
*/
public static function makePermissions(): array
{
$rawPermissions = self::getInstances();
$permissions = [];
collect($rawPermissions)->each(function ($item) use (&$permissions) {
$permissions[] = [
'name' => $item->name,
];
});
return $permissions;
}
/**
* 前置-授权拦截检查.
*
* @return Closure
*/
public static function gateBeforeCallback(): Closure
{
return function ($user, $ability) {
return $user->isSuperAdmin() ?: null;
};
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Enums;
use Jiannei\Enum\Laravel\Repositories\Enums\HttpStatusCodeEnum;
class ResponseCodeEnum extends HttpStatusCodeEnum
{
// 业务操作正确码:1xx、2xx、3xx 开头,后拼接 3 位
// 200 + 001 => 200001,也就是有 001 ~ 999 个编号可以用来表示业务成功的情况,当然你可以根据实际需求继续增加位数,但必须要求是 200 开头
// 举个栗子:你可以定义 001 ~ 099 表示系统状态;100 ~ 199 表示授权业务;200 ~ 299 表示用户业务...
const SERVICE_REGISTER_SUCCESS = 200101;
const SERVICE_LOGIN_SUCCESS = 200102;
// 客户端错误码:400 ~ 499 开头,后拼接 3 位
const CLIENT_PARAMETER_ERROR = 400001;
const CLIENT_CREATED_ERROR = 400002;
const CLIENT_DELETED_ERROR = 400003;
const CLIENT_VALIDATION_ERROR = 422001; // 表单验证错误
// 服务端操作错误码:500 ~ 599 开头,后拼接 3 位
const SYSTEM_ERROR = 500001;
const SYSTEM_UNAVAILABLE = 500002;
const SYSTEM_CACHE_CONFIG_ERROR = 500003;
const SYSTEM_CACHE_MISSED_ERROR = 500004;
const SYSTEM_CONFIG_ERROR = 500005;
// 业务操作错误码(外部服务或内部服务调用...)
const SERVICE_REGISTER_ERROR = 500101;
const SERVICE_LOGIN_ERROR = 500102;
const SERVICE_PASSWORD_UPDATE_ERROR = 500103;
const SERVICE_PASSWORD_ERROR = 500103;
const SERVICE_TOKEN_REFRESH_ERROR = 500105;
const SERVICE_USER_NOT_EXIST_ERROR = 500106;
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Enums;
use Illuminate\Support\Str;
use Jiannei\Enum\Laravel\Contracts\LocalizedEnumContract;
use Jiannei\Enum\Laravel\FlaggedEnum;
class RoleEnum extends FlaggedEnum implements LocalizedEnumContract
{
const GUEST = 1 << 0;
const ADMIN = 1 << 1;
const SUPER_ADMIN = self::GUEST | self::ADMIN;
public $name;
public function __construct($flags)
{
parent::__construct($flags);
$this->name = Str::ucfirst(Str::lower(Str::of($this->key)->replace('_', ' ')));
}
public static function makeRoles(): array
{
$rawRoles = self::getInstances();
collect($rawRoles)->each(function ($item, $key) use (&$roles) {
if ($item->value !== self::NONE) {
$roles[] = ['name' => $item->name];
}
});
return $roles;
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Models;
use App\Repositories\Enums\RoleEnum;
use Database\Factories\UserFactory;
use Illuminate\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Laravel\Lumen\Auth\Authorizable;
use Spatie\Permission\Traits\HasRoles;
use Tymon\JWTAuth\Contracts\JWTSubject;
class AdminUsers extends Model implements AuthenticatableContract, AuthorizableContract, JWTSubject
{
use Authenticatable, Authorizable, HasFactory, HasRoles;
protected $table = 'admin_users';
protected $guard_name = 'api';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'username', 'nickname', 'password', 'email', 'token', 'is_admin', 'status'
];
/**
* The attributes excluded from the model's JSON form.
*
* @var array
*/
protected $hidden = [
];
/**
* Get the identifier that will be stored in the subject claim of the JWT.
*
* @return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* @return array
*/
public function getJWTCustomClaims()
{
return [];
}
public function isSuperAdmin() : bool
{
return $this->is_admin === 1 ? true : false;
}
/**
* 是否是非法禁止使用的用户 status == 0
* @return bool
*/
public function isUnusualUser() : bool
{
return $this->status === 0 ? true : false;
}
public function isOwnerOf(\Illuminate\Database\Eloquent\Model $model, string $key = 'user_id'): bool
{
if ($model instanceof User) {
return $this->id === $model->id;
}
return $this->id === $model->$key;
}
public function encryptPassword($hash) : string
{
$str = base64_encode($hash);
$encodePassword = md5(md5($str));
return $encodePassword;
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Models;
use Jenssegers\Mongodb\Eloquent\Model;
class Log extends Model
{
protected $connection = 'mongodb';
protected $guarded = [];
protected $dates = [
'datetime',
];
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Models;
class Menus extends Model
{
protected $table = 'menus';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'menu_name','menu_path','menu_icon','parent_id','menu_type','component','status','sort','is_show','sys_default','created_by'
];
/**
* The attributes excluded from the model's JSON form.
*
* @var array
*/
protected $hidden = [
];
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Models;
use App\Support\Traits\SerializeDate;
use Illuminate\Database\Eloquent\Model as EloquentModel;
abstract class Model extends EloquentModel
{
use SerializeDate;
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Presenters;
use App\Repositories\Transformers\PostTransformer;
class PostPresenter extends Presenter
{
/**
* Prepare data to present.
*
* @return \League\Fractal\TransformerAbstract
*/
public function getTransformer()
{
return new PostTransformer();
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Presenters;
use Exception;
use Illuminate\Container\Container;
use Illuminate\Database\Eloquent\Collection as EloquentCollection;
use Illuminate\Pagination\AbstractPaginator;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Pagination\Paginator;
use League\Fractal\Pagination\Cursor;
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
use League\Fractal\Resource\Collection;
use Prettus\Repository\Presenter\FractalPresenter;
abstract class Presenter extends FractalPresenter
{
protected $cursor = null;
public function makeCursor($current, $previous, $next, $count)
{
$this->cursor = new Cursor(...func_get_args());
}
/**
* Prepare data to present.
*
* @param $data
* @return mixed
*
* @throws Exception
*/
public function present($data)
{
if (! class_exists('League\Fractal\Manager')) {
throw new Exception(trans('repository::packages.league_fractal_required'));
}
if ($data instanceof EloquentCollection) {
$this->resource = $this->transformCollection($data);
} elseif ($data instanceof AbstractPaginator) {
$this->resource = $this->transformPaginator($data);
} else {
$this->resource = $this->transformItem($data);
}
return $this->fractal->createData($this->resource)->toArray();
}
/**
* @param $data
* @return \League\Fractal\Resource\Collection
*/
protected function transformCollection($data)
{
$resource = new Collection($data, $this->getTransformer(), $this->resourceKeyCollection);
if ($this->cursor) {
$resource->setCursor($this->cursor);
}
return $resource;
}
/**
* @param AbstractPaginator|LengthAwarePaginator|Paginator $paginator
* @return \League\Fractal\Resource\Collection
*/
protected function transformPaginator($paginator)
{
$collection = $paginator->getCollection();
$resource = new Collection($collection, $this->getTransformer(), $this->resourceKeyCollection);
if ($paginator instanceof Paginator) {
$items = $paginator->items();
$total = 0;
$perPage = $paginator->perPage();
$currentPage = $paginator->currentPage();
$options = array_merge(['hasMore' => $paginator->hasMorePages()], $paginator->getOptions());
$paginator = Container::getInstance()->makeWith(LengthAwarePaginator::class, compact(
'items', 'total', 'perPage', 'currentPage', 'options'
));
}
$resource->setPaginator(new IlluminatePaginatorAdapter($paginator));
return $resource;
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Presenters;
use App\Repositories\Transformers\UserTransformer;
class UserPresenter extends Presenter
{
/**
* Prepare data to present.
*
* @return \League\Fractal\TransformerAbstract
*/
public function getTransformer()
{
return new UserTransformer();
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Transformers;
use App\Repositories\Enums\PermissionEnum;
use App\Repositories\Models\Post;
use Illuminate\Support\Str;
use League\Fractal\TransformerAbstract;
class PostTransformer extends TransformerAbstract
{
protected $defaultIncludes = [
'author',
];
public function transform(Post $post)
{
return [
'id' => $post->id,
'title' => $post->title,
'body' => $this->checkColumnPermission() ? $post->body : Str::limit($post->body, 120), // 没有文章详情查看权限时,返回截取的部分内容
'published' => $post->published,
];
}
protected function checkColumnPermission()
{
return auth('api')->user()->can(PermissionEnum::ROUTE_POSTS_VIEW()->name);
}
public function includeAuthor(Post $post)
{
$author = $post->author;
return $this->item($author, new UserTransformer());
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Transformers;
use App\Repositories\Enums\PermissionEnum;
use App\Repositories\Models\User;
use League\Fractal\TransformerAbstract;
class UserTransformer extends TransformerAbstract
{
public function transform(User $user)
{
$data = [
'id' => $user->id,
'nickname' => $user->name,
'email' => $user->email,
];
if (! $this->checkColumnPermission()) {
$data['email'] = '**** ****';
}
return $data;
}
protected function checkColumnPermission()
{
return auth('api')->user()->can(PermissionEnum::DATA_USERS_COLUMN_EMAIL()->name);
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Repositories\Validators;
use Prettus\Validator\Contracts\ValidatorInterface;
use Prettus\Validator\LaravelValidator;
class UserValidator extends LaravelValidator
{
protected $rules = [
ValidatorInterface::RULE_CREATE => [
'username' => 'required|string|max:100',
'email' => 'required|email|unique:users,email',
'password' => 'required|min:8',
],
ValidatorInterface::RULE_UPDATE => [
'password' => 'required|min:8',
],
];
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Services;
use App\Repositories\Contracts\UsersRepository;
use App\Repositories\Criteria\UserCriteria;
use App\Repositories\Presenters\UserPresenter;
use App\Repositories\Enums\ResponseCodeEnum;
use App\Support\Traits\Helpers;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Spatie\Permission\Models\Role;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use App\Repositories\Models\AdminUsers;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
class AuthService
{
use Helpers;
protected $userRepository = null;
public function __construct(UsersRepository $usersRepository)
{
$this->userRepository = $usersRepository;
}
/**
* @param Request $request
*/
public function login(Request $request)
{
$username = $request->input('username');
$password = $request->input('password');
$requestCriteria = [
'username' => $username,
'password' => $password
];
try{
if( !$user = auth()->attempt($requestCriteria) ){
throw new UnauthorizedHttpException('authroization error','用户登陆授权失败,用户名或密码错误',null,ResponseCodeEnum::CLIENT_PARAMETER_ERROR);
}
return $this->generateToken($user);
}catch(\Exception $exception){
throw new UnauthorizedHttpException('authroization error',$exception->getMessage(),null,ResponseCodeEnum::SERVICE_LOGIN_ERROR);
}
}
/**
* 获取登陆用户信息
* @return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function getUserInfo()
{
$user = auth()->user();
//除去敏感信息
if(isset($user['password'])){
unset($user['password']);
}
if(isset($user['token'])){
unset($user['token']);
}
return $user;
}
/**
* 用户列表
* @param $request
* @return array
*/
public function listByPage($request)
{
$params = $this->formatKeysfromArray($request->all(),'toUnderScore');
if(!$params['page_size'] || $params['page_size'] == 0){
$params['page_size'] = 10;
}
$users = $this->userRepository->paginate($params['page_size'],['id','username','nickname','email','token','is_admin','status','lastlogin','created_at','updated_at']);
$returnRecord = [];
if($users){
$allItems = $users->items();
$allItems = collect($allItems)->map(function($item){
$rolesName = [];
$roles = collect($item->roles->toArray())->map(function($role) use (&$rolesName){
$rolesName[] = $role['name'];
unset($role['pivot']);
return $role;
});
$item = $item->toArray();
unset($item['roles']);
$item['roles'] = $roles->toArray();
$item['type'] = $item['is_admin'];
$item['belongTo'] = implode(',',$rolesName);
return $item;
});
// 获取当前角色的所有权限
$returnRecord['data'] = $this->formatKeysfromArray($allItems);
$returnRecord['current_page'] = $users->currentPage();
$returnRecord['total'] = $users->total();
}
return $returnRecord;
}
/**
* 用户登出
* @param Request $request
*/
public function logout(Request $request)
{
auth()->logout();
}
/**
* 刷新token
* @return mixed
* @throws TokenInvalidException
*/
public function refreshToken()
{
$token = auth()->refresh();
if(!$token){
throw new TokenInvalidException('token刷新失败',ResponseCodeEnum::SERVICE_TOKEN_REFRESH_ERROR);
}
return $this->generateToken($token);
}
/**
* 更新或创建新用户
* @param $request
* @return bool
*/
public function saveOrUpdateUser($request)
{
$params = $this->formatKeysfromArray($request->all(),'toUnderScore');
$rule = $this->userRepository->rules['create'];
$filterRuleParams = [];
if(isset($params['id']) && !empty($params['id'])){
$rule = $this->userRepository->rules['update'];
$filterRuleParams['id'] = $params['id'];
}
//整理请求过来的数据参数
collect($rule)->map(function($r,$key) use ($params, &$filterRuleParams){
if(isset($params[$key]) && !empty($params[$key])){
$filterRuleParams[$key] = $params[$key];
}else{
$filterRuleParams[$key] = '';
}
});
if($user = $this->userRepository->createOrUpdateUser($filterRuleParams)){
// 如果编辑用户时选择了所属角色
if(isset($params['role_ids']) && !empty($params['role_ids'])){
$ids = explode(',',$params['role_ids']);
$roles = Role::query()->whereIn('id',$ids)->get();
if(!$roles){
throw new \LogicException('角色不存在');
}
$belongRoles = $user->roles;
//角色
if(count($belongRoles->toArray()) > 0){
collect($belongRoles)->map(function($role) use ($user){
$user->removeRole($role);
$permissions = $role->permissions;
collect($permissions)->map(function($permission) use ($role){
$role->revokePermissionTo($permission);
});
});
}
collect($roles)->map(function($role) use ($user){
$user->assignRole($role);
/*echo "<pre>";
print_R($role->permissions->toArray());
exit;*/
});
}else{
$roles = $user->roles;
if(count($roles->toArray()) > 0){
collect($roles)->map(function($role) use ($user){
$user->removeRole($role);
});
}
}
}
return true;
}
/**
* 更新用户状态
* @param $request
* @param $id
*/
public function updateUserStatus($request, $id)
{
$status = 0;
if(Str::contains(strtolower((string) $request->getPathInfo()), 'disable')){
$status = 0;
}elseif(Str::contains(strtolower((string) $request->getPathInfo()), 'enable')){
$status = 1;
}
$this->userRepository->updateUserStatus($id,$status);
}
/**
* 物理删除用户
* @param $request
*/
public function deleteUser($request)
{
$params = $this->formatKeysfromArray($request->all(),'toUnderScore');
$ids = explode(',',$params['ids']);
$users = $this->userRepository->whereIn('id',$ids)->get();
if(count($users->toArray()) != count($ids)){
throw new \LogicException('部分用户不存在');
}
if($this->userRepository->deleteUser($ids)){
//将用户的角色收回
collect($users)->map(function($user){
$roles = $user->roles;
collect($roles)->map(function($role) use ($user){
$user->removeRole($role);
});
});
}
}
/**
* 重置密码
* @param Request $request
* @return bool
*/
public function resetPassword(Request $request)
{
// 判断旧密码是否正确
$oldPassword = $request->input('oldpassword');
$newPassword = $request->input('newpassword');
$adminModel = app(AdminUsers::class);
$user = $this->userRepository->where('id',auth()->user()->id)->first();
if(!$user){
throw new UnauthorizedHttpException('user not exist. ','不存在该用户',null,ResponseCodeEnum::SERVICE_USER_NOT_EXIST_ERROR);
}
$encodeOldPassword = $adminModel->encryptPassword($oldPassword);
if($encodeOldPassword != $user->password){
throw new UnauthorizedHttpException('password is error. ','密码更新失败:旧密码不正确',null,ResponseCodeEnum::SERVICE_PASSWORD_ERROR);
}
$user->password = $adminModel->encryptPassword($newPassword);
if($encodeOldPassword == $user->password){
throw new UnauthorizedHttpException('password is error. ','新密码不能和旧密码一致',null,ResponseCodeEnum::SERVICE_PASSWORD_ERROR);
}
// 根据role规则重组 user
$updateUser = collect($this->userRepository->rules['update'])->map(function($rule,$key) use ($user){
return $user[$key];
});
$result = $this->userRepository->update($updateUser->toArray(),$user->id);
return true;
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Services;
use App\Repositories\Enums\ResponseCodeEnum;
use App\Support\Traits\Helpers;
use App\Repositories\Contracts\MenusRepository;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Spatie\Permission\Models\Role;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
class MenusService
{
use Helpers;
protected $menuRepository = null;
public function __construct(MenusRepository $menuRepository)
{
$this->menuRepository = $menuRepository;
}
}
This diff is collapsed.
<?php
namespace App\Support\Traits;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
trait Helpers
{
// 取随机码,用于生成session
protected function randomFromDevice($len)
{
$fp = @fopen('/dev/urandom', 'rb');
$result = '';
if ($fp !== FALSE) {
$result .= @fread($fp, $len);
@fclose($fp);
}
else
{
trigger_error('Can not open /dev/urandom.');
}
// convert from binary to string
$result = base64_encode($result);
// remove none url chars
$result = strtr($result, '+/', '-_');
return substr($result, 0, $len);
}
protected function generateToken($hashToken)
{
$expireAt = time() + 3600 * 24;
$appToken = env('JWT_SECRET');
$str = base64_encode(json_encode(['expire'=>$expireAt, 'hash'=>$hashToken])) ;
$sign = md5($str . $appToken);
return 'bearer'.base64_encode($sign . $str);
}
protected function decodeToken($token)
{
$str = base64_decode($token);
$sign = substr($str, 0, 32);
$dataStr = substr($str, 32);
$appToken = env('JWT_SECRET');
if($sign != md5($dataStr . $appToken))
{
throw new UnauthorizedHttpException("sign error");
}
$dataJson = base64_decode($dataStr);
$data = json_decode($dataJson, 1);
if($data['expire'] < time())
{
throw new UnauthorizedHttpException("token expired","身份验证失效,请重新登录");
}
return $data;
}
public static function print($arr){
echo "<pre>";
print_R($arr);
}
//驼峰命名转下划线命名
protected function toUnderScore($str)
{
$dstr = preg_replace_callback('/([A-Z]+)/',function($matchs)
{
return '_'.strtolower($matchs[0]);
},$str);
return trim(preg_replace('/_{2,}/','_',$dstr),'_');
}
//下划线命名到驼峰命名
protected function toCamelCase($str)
{
$array = explode('_', $str);
$result = $array[0];
$len=count($array);
if($len>1)
{
for($i=1;$i<$len;$i++)
{
$result.= ucfirst($array[$i]);
}
}
return $result;
}
/**
* 将多维数组中的key转换类型
* toCamelCase : 将下划线转换为驼峰格式 toUnderScore : 将驼峰转换为下划线分割
* @param $arr
* @param string $type
* @return array
*/
public function formatKeysfromArray($arr, $type = 'toCamelCase'){
if(!is_array($arr)){
$arr = $arr->toArray();
}
$newArr = [];
collect($arr)->map(function($value, $key) use ( &$newArr, $type){
if(!is_array($value)){
switch($type) {
case 'toCamelCase' :
$newKey = $this->toCamelCase($key);
break;
case 'toUnderScore' :
$newKey = $this->toUnderScore($key);
break;
default:
$newKey = $this->toCamelCase($key);
}
$newArr[$newKey] = $value;
}else{
$val = $this->formatKeysfromArray($value,$type);
$newArr[$key] = $val;
}
});
return $newArr;
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
namespace App\Support\Traits;
use Carbon\Carbon;
use DateTimeInterface;
trait SerializeDate
{
/**
* 为数组 / JSON 序列化准备日期。(Laravel 7).
*
* @param \DateTimeInterface $date
* @return string
*/
protected function serializeDate(DateTimeInterface $date)
{
return $date->format($this->dateFormat ?: Carbon::DEFAULT_TO_STRING_FORMAT);
}
}
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
#!/usr/bin/env php
<?php
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Console\Output\ConsoleOutput;
/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
|
| First we need to get an application instance. This creates an instance
| of the application / container and bootstraps the application so it
| is ready to receive HTTP / Console requests from the environment.
|
*/
$app = require __DIR__.'/bootstrap/app.php';
/*
|--------------------------------------------------------------------------
| Run The Artisan Application
|--------------------------------------------------------------------------
|
| When we run the console application, the current CLI command will be
| executed in this console and the response sent back to a terminal
| or another output device for the developers. Here goes nothing!
|
*/
$kernel = $app->make(
'Illuminate\Contracts\Console\Kernel'
);
exit($kernel->handle(new ArgvInput, new ConsoleOutput));
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
require_once __DIR__.'/../vendor/autoload.php';
(new Laravel\Lumen\Bootstrap\LoadEnvironmentVariables(
dirname(__DIR__)
))->bootstrap();
date_default_timezone_set(env('APP_TIMEZONE', 'UTC'));
/*
|--------------------------------------------------------------------------
| Create The Application
|--------------------------------------------------------------------------
|
| Here we will load the environment and create the application instance
| that serves as the central piece of this framework. We'll use this
| application as an "IoC" container and router for this framework.
|
*/
$app = new Laravel\Lumen\Application(
dirname(__DIR__)
);
$app->withFacades();
//$app->register(Jenssegers\Mongodb\MongodbServiceProvider::class);
$app->withEloquent();
/*
|--------------------------------------------------------------------------
| Register Container Bindings
|--------------------------------------------------------------------------
|
| Now we will register a few bindings in the service container. We will
| register the exception handler and the console kernel. You may add
| your own bindings here if you like or you can make another file.
|
*/
$app->singleton(
Illuminate\Contracts\Debug\ExceptionHandler::class,
App\Exceptions\Handler::class
);
$app->singleton(
Illuminate\Contracts\Console\Kernel::class,
App\Console\Kernel::class
);
/*
|--------------------------------------------------------------------------
| Register Config Files
|--------------------------------------------------------------------------
|
| Now we will register the "app" configuration file. If the file exists in
| your configuration directory it will be loaded; otherwise, we'll load
| the default version. You may register other files below as needed.
|
*/
$app->configure('app');
$app->configure('auth');
$app->configure('broadcasting');
$app->configure('cache');
$app->configure('database');
$app->configure('filesystems');
$app->configure('logging');
$app->configure('queue');
$app->configure('services');
$app->configure('view');
$app->configure('repository');
$app->configure('enum');
$app->configure('permission');
$app->configure('response');
$app->alias('cache', \Illuminate\Cache\CacheManager::class);
/*
|--------------------------------------------------------------------------
| Register Middleware
|--------------------------------------------------------------------------
|
| Next, we will register the middleware with the application. These can
| be global middleware that run before and after each request into a
| route or middleware that'll be assigned to some specific routes.
|
*/
$app->middleware([
\Jiannei\Logger\Laravel\Http\Middleware\RequestLog::class,
\Jiannei\Response\Laravel\Http\Middleware\Etag::class,
]);
$app->routeMiddleware([
'superadmin' => App\Http\Middleware\Authenticate::class,
//'userRole' => App\Http\Middleware\UserPermissionMiddleware::class,
//'enum' => \Jiannei\Enum\Laravel\Http\Middleware\TransformEnums::class,
//'permission' => \Spatie\Permission\Middlewares\PermissionMiddleware::class,
//'role' => \Spatie\Permission\Middlewares\RoleMiddleware::class,
'throttle' => \Jiannei\Response\Laravel\Http\Middleware\ThrottleRequests::class,
]);
/*
|--------------------------------------------------------------------------
| Register Service Providers
|--------------------------------------------------------------------------
|
| Here we will register all of the application's service providers which
| are used to bind services into the container. Service providers are
| totally optional, so you are not required to uncomment this line.
|
*/
/*
* Application Service Providers...
*/
$app->register(App\Providers\AppServiceProvider::class);
$app->register(App\Providers\AuthServiceProvider::class);
$app->register(App\Providers\RepositoryServiceProvider::class);
//$app->register(App\Providers\EventServiceProvider::class);
/*
* Package Service Providers...
*/
$app->register(\Tymon\JWTAuth\Providers\LumenServiceProvider::class);
$app->register(\Illuminate\Redis\RedisServiceProvider::class);
//$app->register(\Spatie\Permission\PermissionServiceProvider::class);
$app->register(Dingo\Api\Provider\LumenServiceProvider::class);
$app->register(\Jiannei\Enum\Laravel\Providers\LumenServiceProvider::class);
$app->register(\Jiannei\Response\Laravel\Providers\LumenServiceProvider::class);
$app->register(\Jiannei\Logger\Laravel\Providers\ServiceProvider::class);
/*
|--------------------------------------------------------------------------
| Load The Application Routes
|--------------------------------------------------------------------------
|
| Next we will include the routes file so that they can all be added to
| the application. This will provide all of the URLs the application
| can respond to, as well as the controllers that may handle them.
|
*/
$app->router->group([
'namespace' => 'App\Http\Controllers',
], function ($app) {
//require __DIR__.'/../routes/web.php';
require_once __DIR__.'/route.php';
});
return $app;
<?php
/*$app->router->group(['namespace' => 'WechatBundle\Http\Controllers'], function ($app) {
require __DIR__.'/../routes/web.php';
});*/
//$api = app('api.router');
$api = app('Dingo\Api\Routing\Router');
require __DIR__.'/../routes/api/auth.php';
return $app;
{
"name": "laravel/lumen",
"description": "The Laravel Lumen Framework.",
"keywords": ["framework", "laravel", "lumen"],
"license": "MIT",
"type": "project",
"require": {
"php": "^7.3|^8.0",
"ext-json": "*",
"api-ecosystem-for-laravel/dingo-api": "^3.1",
"fruitcake/laravel-cors": "^3.0",
"guzzlehttp/guzzle": "^7.3",
"illuminate/redis": "^8.34",
"jiannei/laravel-enum": "^3.0",
"jiannei/laravel-logger": "^1.2",
"jiannei/laravel-response": "^4.0",
"laravel/lumen-framework": "^8.0",
"league/fractal": "^0.19.2",
"prettus/l5-repository": "^2.7",
"spatie/laravel-permission": "^5.1",
"tymon/jwt-auth": "^1.0.2"
},
"require-dev": {
"fzaninotto/faker": "^1.9.1",
"mockery/mockery": "^1.3.1",
"phpunit/phpunit": "^9.3"
},
"autoload": {
"files": [
"app/Support/helpers.php"
],
"classmap": [
"database/seeds",
"database/factories"
],
"psr-4": {
"App\\": "app/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"config": {
"preferred-install": "dist",
"sort-packages": true,
"optimize-autoloader": true
},
"minimum-stability": "dev",
"prefer-stable": true,
"scripts": {
"post-root-package-install": [
"@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
]
}
}
<?php
return [
/*
|--------------------------------------------------------------------------
| Standards Tree
|--------------------------------------------------------------------------
|
| Versioning an API with Dingo revolves around content negotiation and
| custom MIME types. A custom type will belong to one of three
| standards trees, the Vendor tree (vnd), the Personal tree
| (prs), and the Unregistered tree (x).
|
| By default the Unregistered tree (x) is used, however, should you wish
| to you can register your type with the IANA. For more details:
| https://tools.ietf.org/html/rfc6838
|
*/
'standardsTree' => env('API_STANDARDS_TREE', 'x'),
/*
|--------------------------------------------------------------------------
| API Subtype
|--------------------------------------------------------------------------
|
| Your subtype will follow the standards tree you use when used in the
| "Accept" header to negotiate the content type and version.
|
| For example: Accept: application/x.SUBTYPE.v1+json
|
*/
'subtype' => env('API_SUBTYPE', ''),
/*
|--------------------------------------------------------------------------
| Default API Version
|--------------------------------------------------------------------------
|
| This is the default version when strict mode is disabled and your API
| is accessed via a web browser. It's also used as the default version
| when generating your APIs documentation.
|
*/
'version' => env('API_VERSION', 'v1'),
/*
|--------------------------------------------------------------------------
| Default API Prefix
|--------------------------------------------------------------------------
|
| A default prefix to use for your API routes so you don't have to
| specify it for each group.
|
*/
'prefix' => env('API_PREFIX', null),
/*
|--------------------------------------------------------------------------
| Default API Domain
|--------------------------------------------------------------------------
|
| A default domain to use for your API routes so you don't have to
| specify it for each group.
|
*/
'domain' => env('API_DOMAIN', null),
/*
|--------------------------------------------------------------------------
| Name
|--------------------------------------------------------------------------
|
| When documenting your API using the API Blueprint syntax you can
| configure a default name to avoid having to manually specify
| one when using the command.
|
*/
'name' => env('API_NAME', null),
/*
|--------------------------------------------------------------------------
| Conditional Requests
|--------------------------------------------------------------------------
|
| Globally enable conditional requests so that an ETag header is added to
| any successful response. Subsequent requests will perform a check and
| will return a 304 Not Modified. This can also be enabled or disabled
| on certain groups or routes.
|
*/
'conditionalRequest' => env('API_CONDITIONAL_REQUEST', true),
/*
|--------------------------------------------------------------------------
| Strict Mode
|--------------------------------------------------------------------------
|
| Enabling strict mode will require clients to send a valid Accept header
| with every request. This also voids the default API version, meaning
| your API will not be browsable via a web browser.
|
*/
'strict' => env('API_STRICT', false),
/*
|--------------------------------------------------------------------------
| Debug Mode
|--------------------------------------------------------------------------
|
| Enabling debug mode will result in error responses caused by thrown
| exceptions to have a "debug" key that will be populated with
| more detailed information on the exception.
|
*/
'debug' => env('API_DEBUG', false),
/*
|--------------------------------------------------------------------------
| Generic Error Format
|--------------------------------------------------------------------------
|
| When some HTTP exceptions are not caught and dealt with the API will
| generate a generic error response in the format provided. Any
| keys that aren't replaced with corresponding values will be
| removed from the final response.
|
*/
'errorFormat' => [
'error' => [
'message' => ':message',
'errors' => ':errors',
'code' => ':code',
'status_code' => ':status_code',
'debug' => ':debug',
],
],
/*
|--------------------------------------------------------------------------
| API Middleware
|--------------------------------------------------------------------------
|
| Middleware that will be applied globally to all API requests.
|
*/
'middleware' => [
],
/*
|--------------------------------------------------------------------------
| Authentication Providers
|--------------------------------------------------------------------------
|
| The authentication providers that should be used when attempting to
| authenticate an incoming API request.
|
*/
'auth' => [
'jwt' => App\Providers\Auth\Jwt\AdminAuthProvider::class,
],
/*
|--------------------------------------------------------------------------
| Throttling / Rate Limiting
|--------------------------------------------------------------------------
|
| Consumers of your API can be limited to the amount of requests they can
| make. You can create your own throttles or simply change the default
| throttles.
|
*/
'throttling' => [
],
/*
|--------------------------------------------------------------------------
| Response Transformer
|--------------------------------------------------------------------------
|
| Responses can be transformed so that they are easier to format. By
| default a Fractal transformer will be used to transform any
| responses prior to formatting. You can easily replace
| this with your own transformer.
|
*/
'transformer' => env('API_TRANSFORMER', Dingo\Api\Transformer\Adapter\Fractal::class),
/*
|--------------------------------------------------------------------------
| Response Formats
|--------------------------------------------------------------------------
|
| Responses can be returned in multiple formats by registering different
| response formatters. You can also customize an existing response
| formatter.
|
*/
'defaultFormat' => env('API_DEFAULT_FORMAT', 'json'),
'formats' => [
'json' => Dingo\Api\Http\Response\Format\Json::class,
],
];
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
return [
/*
|--------------------------------------------------------------------------
| Application Name
|--------------------------------------------------------------------------
|
| This value is the name of your application. This value is used when the
| framework needs to place the application's name in a notification or
| any other location as required by the application or its packages.
|
*/
'name' => env('APP_NAME', 'Lumen'),
/*
|--------------------------------------------------------------------------
| Application Environment
|--------------------------------------------------------------------------
|
| This value determines the "environment" your application is currently
| running in. This may determine how you prefer to configure various
| services the application utilizes. Set this in your ".env" file.
|
*/
'env' => env('APP_ENV', 'production'),
/*
|--------------------------------------------------------------------------
| Application Debug Mode
|--------------------------------------------------------------------------
|
| When your application is in debug mode, detailed error messages with
| stack traces will be shown on every error that occurs within your
| application. If disabled, a simple generic error page is shown.
|
*/
'debug' => env('APP_DEBUG', false),
/*
|--------------------------------------------------------------------------
| Application URL
|--------------------------------------------------------------------------
|
| This URL is used by the console to properly generate URLs when using
| the Artisan command line tool. You should set this to the root of
| your application so that it is used when running Artisan tasks.
|
*/
'url' => env('APP_URL', 'http://localhost'),
/*
|--------------------------------------------------------------------------
| Application Timezone
|--------------------------------------------------------------------------
|
| Here you may specify the default timezone for your application, which
| will be used by the PHP date and date-time functions. We have gone
| ahead and set this to a sensible default for you out of the box.
|
*/
'timezone' => env('APP_TIMEZONE', 'UTC'),
/*
|--------------------------------------------------------------------------
| Application Locale Configuration
|--------------------------------------------------------------------------
|
| The application locale determines the default locale that will be used
| by the translation service provider. You are free to set this value
| to any of the locales which will be supported by the application.
|
*/
'locale' => env('APP_LOCALE', 'en'),
/*
|--------------------------------------------------------------------------
| Application Fallback Locale
|--------------------------------------------------------------------------
|
| The fallback locale determines the locale to use when the current one
| is not available. You may change the value to correspond to any of
| the language folders that are provided through your application.
|
*/
'fallback_locale' => env('APP_FALLBACK_LOCALE', 'en'),
/*
|--------------------------------------------------------------------------
| Encryption Key
|--------------------------------------------------------------------------
|
| This key is used by the Illuminate encrypter service and should be set
| to a random, 32 character string, otherwise these encrypted strings
| will not be safe. Please do this before deploying an application!
|
*/
'key' => env('APP_KEY'),
'cipher' => 'AES-256-CBC',
];
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
return [
/*
|--------------------------------------------------------------------------
| Authentication Defaults
|--------------------------------------------------------------------------
|
| This option controls the default authentication "guard" and password
| reset options for your application. You may change these defaults
| as required, but they're a perfect start for most applications.
|
*/
'defaults' => [
'guard' => env('AUTH_GUARD', 'api'),
],
/*
|--------------------------------------------------------------------------
| Authentication Guards
|--------------------------------------------------------------------------
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| here which uses session storage and the Eloquent user provider.
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| Supported: "token"
|
*/
'guards' => [
'api' => [
'driver' => 'jwt',
'provider' => 'users', // 与下面的 providers 中的 users 是对应的
],
],
/*
|--------------------------------------------------------------------------
| User Providers
|--------------------------------------------------------------------------
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| If you have multiple user tables or models you may configure multiple
| sources which represent each model / table. These sources may then
| be assigned to any extra authentication guards you have defined.
|
| Supported: "database", "eloquent"
|
*/
'providers' => [
'users' => [
'driver' => 'superadmin',
'model' => \App\Repositories\Models\AdminUsers::class,
],
],
/*
|--------------------------------------------------------------------------
| Resetting Passwords
|--------------------------------------------------------------------------
|
| Here you may set the options for resetting passwords including the view
| that is your password reset e-mail. You may also set the name of the
| table that maintains all of the reset tokens for your application.
|
| You may specify multiple password reset configurations if you have more
| than one user table or model in the application and you want to have
| separate password reset settings based on the specific user types.
|
| The expire time is the number of minutes that the reset token should be
| considered valid. This security feature keeps tokens short-lived so
| they have less time to be guessed. You may change this as needed.
|
*/
'passwords' => [
],
];
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
return [
/*
|--------------------------------------------------------------------------
| Default Broadcaster
|--------------------------------------------------------------------------
|
| This option controls the default broadcaster that will be used by the
| framework when an event needs to be broadcast. You may set this to
| any of the connections defined in the "connections" array below.
|
| Supported: "pusher", "redis", "log", "null"
|
*/
'default' => env('BROADCAST_DRIVER', 'null'),
/*
|--------------------------------------------------------------------------
| Broadcast Connections
|--------------------------------------------------------------------------
|
| Here you may define all of the broadcast connections that will be used
| to broadcast events to other systems or over websockets. Samples of
| each available type of connection are provided inside this array.
|
*/
'connections' => [
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => env('PUSHER_APP_CLUSTER'),
'encrypted' => true,
],
],
'redis' => [
'driver' => 'redis',
'connection' => env('BROADCAST_REDIS_CONNECTION', 'default'),
],
'log' => [
'driver' => 'log',
],
'null' => [
'driver' => 'null',
],
],
];
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
use Illuminate\Support\Str;
return [
/*
|--------------------------------------------------------------------------
| Default Cache Store
|--------------------------------------------------------------------------
|
| This option controls the default cache connection that gets used while
| using this caching library. This connection is used when another is
| not explicitly specified when executing a given caching function.
|
| Supported: "apc", "array", "database", "file", "memcached", "redis"
|
*/
'default' => env('CACHE_DRIVER', 'file'),
/*
|--------------------------------------------------------------------------
| Cache Stores
|--------------------------------------------------------------------------
|
| Here you may define all of the cache "stores" for your application as
| well as their drivers. You may even define multiple stores for the
| same cache driver to group types of items stored in your caches.
|
*/
'stores' => [
'apc' => [
'driver' => 'apc',
],
'array' => [
'driver' => 'array',
],
'database' => [
'driver' => 'database',
'table' => env('CACHE_DATABASE_TABLE', 'cache'),
'connection' => env('CACHE_DATABASE_CONNECTION', null),
],
'file' => [
'driver' => 'file',
'path' => storage_path('framework/cache/data'),
],
'memcached' => [
'driver' => 'memcached',
'persistent_id' => env('MEMCACHED_PERSISTENT_ID'),
'sasl' => [
env('MEMCACHED_USERNAME'),
env('MEMCACHED_PASSWORD'),
],
'options' => [
// Memcached::OPT_CONNECT_TIMEOUT => 2000,
],
'servers' => [
[
'host' => env('MEMCACHED_HOST', '127.0.0.1'),
'port' => env('MEMCACHED_PORT', 11211),
'weight' => 100,
],
],
],
'redis' => [
'driver' => 'redis',
'connection' => env('CACHE_REDIS_CONNECTION', 'default'),
],
],
/*
|--------------------------------------------------------------------------
| Cache Key Prefix
|--------------------------------------------------------------------------
|
| When utilizing a RAM based store such as APC or Memcached, there might
| be other applications utilizing the same cache. So, we'll specify a
| value to get prefixed to all our keys so we can avoid collisions.
|
*/
'prefix' => env(
'CACHE_PREFIX',
Str::slug(env('APP_NAME', 'lumen'), '_').'_cache'
),
];
<?php
/*
* This file is part of the Jiannei/lumen-api-starter.
*
* (c) Jiannei <longjian.huang@foxmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/
return [
/*
|--------------------------------------------------------------------------
| Default Database Connection Name
|--------------------------------------------------------------------------
|
| Here you may specify which of the database connections below you wish
| to use as your default connection for all database work. Of course
| you may use many connections at once using the Database library.
|
*/
'default' => env('DB_CONNECTION', 'mysql'),
/*
|--------------------------------------------------------------------------
| Database Connections
|--------------------------------------------------------------------------
|
| Here are each of the database connections setup for your application.
| Of course, examples of configuring each database platform that is
| supported by Laravel is shown below to make development simple.
|
|
| All database work in Laravel is done through the PHP PDO facilities
| so make sure you have the driver for your particular database of
| choice installed on your machine before you begin development.
|
*/
'connections' => [
'sqlite' => [
'driver' => 'sqlite',
'database' => env('DB_DATABASE', database_path('database.sqlite')),
'prefix' => env('DB_PREFIX', ''),
],
'mysql' => [
'driver' => 'mysql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', 3306),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'unix_socket' => env('DB_SOCKET', ''),
'charset' => env('DB_CHARSET', 'utf8mb4'),
'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
'prefix' => env('DB_PREFIX', ''),
'strict' => env('DB_STRICT_MODE', true),
'engine' => env('DB_ENGINE', null),
'timezone' => env('DB_TIMEZONE', '+00:00'),
],
'pgsql' => [
'driver' => 'pgsql',
'host' => env('DB_HOST', '127.0.0.1'),
'port' => env('DB_PORT', 5432),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => env('DB_CHARSET', 'utf8'),
'prefix' => env('DB_PREFIX', ''),
'schema' => env('DB_SCHEMA', 'public'),
'sslmode' => env('DB_SSL_MODE', 'prefer'),
],
'sqlsrv' => [
'driver' => 'sqlsrv',
'host' => env('DB_HOST', 'localhost'),
'port' => env('DB_PORT', 1433),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => env('DB_CHARSET', 'utf8'),
'prefix' => env('DB_PREFIX', ''),
],
'mongodb' => [
'driver' => 'mongodb',
'host' => env('MONGODB_HOST', '127.0.0.1'),
'port' => env('MONGODB_PORT', 27017),
'username' => env('MONGODB_USERNAME', ''),
'password' => env('MONGODB_PASSWORD', ''),
'database' => env('MONGODB_DATABASE', ''),
'options' => [
// here you can pass more settings to the Mongo Driver Manager
// see https://www.php.net/manual/en/mongodb-driver-manager.construct.php under "Uri Options" for a list of complete parameters that you can use
'database' => env('MONGODB_AUTHENTICATION_DATABASE', 'admin'), // required with Mongo 3+
],
],
],
/*
|--------------------------------------------------------------------------
| Migration Repository Table
|--------------------------------------------------------------------------
|
| This table keeps track of all the migrations that have already run for
| your application. Using this information, we can determine which of
| the migrations on disk haven't actually been run in the database.
|
*/
'migrations' => 'migrations',
/*
|--------------------------------------------------------------------------
| Redis Databases
|--------------------------------------------------------------------------
|
| Redis is an open source, fast, and advanced key-value store that also
| provides a richer set of commands than a typical key-value systems
| such as APC or Memcached. Laravel makes it easy to dig right in.
|
*/
'redis' => [
'client' => env('REDIS_CLIENT', 'phpredis'),
'cluster' => env('REDIS_CLUSTER', false),
'default' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_DB', 0),
],
'cache' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_CACHE_DB', 1),
],
'queue' => [
'host' => env('REDIS_HOST', '127.0.0.1'),
'password' => env('REDIS_PASSWORD', null),
'port' => env('REDIS_PORT', 6379),
'database' => env('REDIS_QUEUE_DB', 2),
],
],
];
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
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