Преглед изворни кода

Merge branch 'user_info' into forget-password

# Conflicts:
#	routes/api.php
kely пре 8 месеци
родитељ
комит
62c5dc3e6d

+ 91 - 0
app/Http/Controllers/API/CompanyController.php

@@ -9,13 +9,29 @@
 namespace App\Http\Controllers\API;
 
 
+use App\Mail\CompanyAction;
+use App\Models\CaptchaMail;
+use App\Models\Enums\FileObjectType;
+use App\Models\File;
+use App\Models\Role;
+use App\Services\Notification\ActionEmail\ActionEmailService;
+use Illuminate\Mail\Mailable;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Hash;
+use Illuminate\Support\Facades\Mail;
+use function App\Http\Controllers\badRequest;
 use App\Http\Controllers\Controller;
+
+use App\Http\Requests\API\Company\ActionRequest;
 use App\Http\Requests\API\Company\CreateOrUpdateRequest;
 use App\Http\Resources\API\CompanyResource;
 use App\Models\Company;
 use App\Models\User;
+use App\Services\File\FileAssociationService;
+use Carbon\Carbon;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Auth;
+use App\Models\Enums\CompanyReviewStatus;
 
 class CompanyController extends Controller
 {
@@ -77,4 +93,79 @@ class CompanyController extends Controller
 
         return $this->noContent();
     }
+
+    //注册用户时注册公司
+    public function registerCompany(FileAssociationService $service,CreateOrUpdateRequest $request)
+    {
+        $company = new Company();
+
+        $company->fill([
+            ...$request->all(),
+        ]);
+
+        $company->save();
+
+        $this->filesAssociationCompany($request->get("file_ids", []), FileObjectType::COMPANY,$company->id);
+
+
+        return $this->created();
+    }
+
+    public function filesAssociationCompany(array $fileIds, FileObjectType $fileObjectType,string $companyId){
+        if (! $fileIds) {
+            return;
+        }
+        foreach ($fileIds as $fileId){
+            $file=File::query()
+                ->where('object_type',$fileObjectType->value)
+                ->whereNull("object_id")
+                ->where('id',$fileId)
+                ->first();
+            $file->company_id=$companyId;
+            $file->object_id =$companyId;
+            $file->save();
+        }
+
+    }
+
+    //公司审核
+    public function action(ActionRequest $request){
+        $company = Company::findOrFail($request->id);
+        $status=$request->get('status');
+        $expDate=$request->get('exp_date');
+        $roleId=$request->get('role_id');
+        $rejectReason=$request->get('reject_reason');
+        $user = new User();
+        //通过审核->改变公司状态->设置公司过期时间->最后生成默认账户
+        DB::transaction(function () use($status,$expDate,$company,$user,$roleId){
+        if ($status == 1){
+            //1.改变公司状态->设置公司过期时间
+            $company->review_status=CompanyReviewStatus::APPROVED;
+            $company->exp_date = $expDate === null ? Carbon::now()->addYear()->toDateString():$expDate;
+            //2.生成默认账户
+            $user->name='admin_'.$company->name;
+            $user->email=$company->email;
+            $user->username=$company->email;
+            $user->company_id=$company->id;
+            $user->password=Hash::make('admin@#123');
+            //TODO 此处给的默认角色为硬编码,暂未设置默认角色为哪个
+            $role = Role::query()->findOrFail($roleId);
+            $user->syncRoles($role);
+//            $user->role_id=6;
+//            $user->syncRoles(6);
+            $user->save();
+        }else{
+            $company->review_status=CompanyReviewStatus::REJECTED;
+        }
+        //公司保存
+        $company->save();
+        });
+        //发送邮件到公司账户
+        Mail::to($company->email)->send(new CompanyAction($company,$user,$rejectReason));
+        return $this->noContent();
+    }
+
+
+
+
 }

+ 10 - 0
app/Http/Controllers/API/FileController.php

@@ -15,6 +15,7 @@ use App\Models\Folder;
 use App\Services\File\BIM\BIMFactory;
 use App\Services\File\DownloadService;
 use App\Services\File\FileHideService;
+use App\Services\File\Upload\CompanyUploadService;
 use App\Services\File\Upload\FilesUploadService;
 use App\Services\File\Upload\KeepDirectoryUploadService;
 use Illuminate\Http\Request;
@@ -128,6 +129,15 @@ class FileController extends Controller
 
     }
 
+    public function companyUpload(FileUploadRequest $request){
+        set_time_limit(0);
+        $uploadedFiles = (new CompanyUploadService($request))->upload();
+
+        return $this->success([
+            'data' => $uploadedFiles
+        ]);
+    }
+
 
     /**
      * 文件夹上传

+ 16 - 0
app/Http/Controllers/API/UserController.php

@@ -5,6 +5,7 @@ namespace App\Http\Controllers\API;
 use App\Http\Controllers\Controller;
 use App\Http\Requests\API\User\AdminUpdateRequest;
 use App\Http\Requests\API\User\BatchCreateRequest;
+use App\Http\Requests\API\User\CreateCompanyUserRequest;
 use App\Http\Requests\API\User\CreateRequest;
 use App\Http\Requests\API\User\UpdateRequest;
 use App\Http\Resources\API\UserInfoResource;
@@ -212,4 +213,19 @@ class UserController extends Controller
 //
 //    }
 
+//    /**
+//     * 注册用户
+//     * @return \Illuminate\Http\Response
+//     */
+//    public function registerCompanyUser(CreateCompanyUserRequest $request){
+//        $password = Hash::make($request->password);
+//        $userRequest=$request->all();
+//        $userRequest['password']=$password;
+//        User::create([
+//            ...$userRequest,
+//            'created_by' => Auth::id(),
+//        ]);
+//        return $this->created();
+//    }
+
 }

+ 2 - 0
app/Http/Kernel.php

@@ -2,6 +2,7 @@
 
 namespace App\Http;
 
+use App\Http\Middleware\AccountLimit;
 use App\Http\Middleware\CheckPermission;
 use App\Http\Middleware\SuperAdmin;
 use Illuminate\Foundation\Http\Kernel as HttpKernel;
@@ -68,5 +69,6 @@ class Kernel extends HttpKernel
         'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
         'permission' => CheckPermission::class,
         'role.super-admin' => SuperAdmin::class,
+        'account.limit' => AccountLimit::class,
     ];
 }

+ 29 - 0
app/Http/Middleware/AccountLimit.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace App\Http\Middleware;
+
+use App\Models\Enums\CompanyReviewStatus;
+use Carbon\Carbon;
+use Closure;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Auth;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\Exception\HttpException;
+
+class AccountLimit
+{
+    /**
+     * Handle an incoming request.
+     *
+     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
+     */
+    public function handle(Request $request, Closure $next): Response
+    {
+
+        if (Auth::user()->company->review_status === CompanyReviewStatus::APPROVED->value && Auth::user()->status ===1 &&Carbon::parse(Auth::user()->company->exp_date)->gt(Carbon::now())) {
+            return $next($request);
+        }
+
+        throw new HttpException(403, "Sorry, the account's authorization expires or is denied");
+    }
+}

+ 2 - 0
app/Http/Middleware/CheckPermission.php

@@ -2,6 +2,7 @@
 
 namespace App\Http\Middleware;
 
+use App\Models\Enums\CompanyReviewStatus;
 use Closure;
 use Illuminate\Http\Request;
 use Illuminate\Support\Facades\Auth;
@@ -9,6 +10,7 @@ use Illuminate\Support\Facades\Route;
 use Spatie\Permission\Exceptions\UnauthorizedException;
 use Symfony\Component\HttpFoundation\Response;
 use App\Models\Enums\PermissionType;
+use Symfony\Component\HttpKernel\Event\ExceptionEvent;
 
 class CheckPermission
 {

+ 53 - 0
app/Http/Requests/API/Company/ActionRequest.php

@@ -0,0 +1,53 @@
+<?php
+/**
+ * Created by IntelliJ IDEA.
+ * User: kelyliang
+ * Date: 2024/6/27
+ * Time: 下午 03:58
+ */
+
+namespace App\Http\Requests\API\Company;
+
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class ActionRequest  extends FormRequest
+{
+    public function authorize(): bool
+    {
+        return true;
+    }
+
+    /**
+     * Get the validation rules that apply to the request.
+     *
+     * @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
+     */
+    public function rules(): array
+    {
+        $rules =  [
+            "status" => "required|in:1,0",
+            "id" => "required",
+            //'role_id'=>"required",
+            //'email'=>"required|email",
+        ];
+        if($this->status==1){
+            $rules = [
+                ...$rules,
+                'role_id'=>"required",
+            ];
+
+        }
+        if($this->status==0){
+            $rules = [
+                ...$rules,
+                'reject_reason'=>"required",
+            ];
+
+        }
+         return $rules;
+}
+
+
+
+}

+ 1 - 0
app/Http/Requests/API/Company/CreateOrUpdateRequest.php

@@ -29,6 +29,7 @@ class CreateOrUpdateRequest extends FormRequest
     {
         return [
             'name' => 'required|unique:company,name,NULL,id,deleted_at,NULL',
+            'email' => 'required'
         ];
     }
 

+ 38 - 0
app/Http/Requests/API/User/CreateCompanyUserRequest.php

@@ -0,0 +1,38 @@
+<?php
+/**
+ * Created by IntelliJ IDEA.
+ * User: kelyliang
+ * Date: 2024/6/27
+ * Time: 上午 10:21
+ */
+
+namespace App\Http\Requests\API\User;
+
+
+use Illuminate\Foundation\Http\FormRequest;
+
+class CreateCompanyUserRequest extends FormRequest
+{
+    use RuleHelper;
+
+    /**
+     * Determine if the user is authorized to make this request.
+     */
+    public function authorize(): bool
+    {
+        return true;
+    }
+
+    public function rules(): array
+    {
+
+        return [
+            'name' => 'required|max:100',
+            'email' => 'required|email|unique:users',
+            'username'=>'required|max:30|unique:users',
+            'password' => 'required|min:6|regex:/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{6,}$/', // 至少6位,包含大小写字母和数字,At least 6 digits, including upper and lower case letters and numbers
+            'phone'=>'nullable|regex:/^\d{8,11}$/',
+            'company_id'=>'required|exists:company,id',
+        ];
+    }
+}

+ 1 - 0
app/Http/Resources/API/CompanyResource.php

@@ -20,6 +20,7 @@ class CompanyResource extends JsonResource
           'id' => $this->id,
           'name' => $this->name,
           'email' => $this->email,
+          'review_status' => $this->review_status,
         ];
     }
 

+ 1 - 1
app/Http/Resources/API/FileByObjectResource.php

@@ -21,7 +21,7 @@ class FileByObjectResource extends JsonResource
             'extension' => $this->extension,
             'download_url' => Storage::url($this->pathname),
             'size' => $this->size,
-            'created_by' => new UserProfileResource($this->createdBy),
+            'created_by' => $this->createdBy?new UserProfileResource($this->createdBy):null,
             'created_at' => (string)$this->created_at,
             'version' => $this->version,
         ];

+ 66 - 0
app/Mail/CompanyAction.php

@@ -0,0 +1,66 @@
+<?php
+
+namespace App\Mail;
+
+use App\Models\Company;
+use App\Models\Enums\ObjectAction;
+use App\Models\Task;
+use App\Models\User;
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Mail\Mailable;
+use Illuminate\Mail\Mailables\Content;
+use Illuminate\Mail\Mailables\Envelope;
+use Illuminate\Queue\SerializesModels;
+
+class CompanyAction extends Mailable
+{
+    use Queueable, SerializesModels;
+
+//    private $company;
+//    private $user;
+
+    /**
+     * Create a new message instance.
+     */
+    public function __construct(public Company $company,public User $user,public string $rejectReason)
+    {
+//        $this->company = $company;
+//        $this->user = $user;
+    }
+
+    /**
+     * Get the message envelope.
+     */
+    public function envelope(): Envelope
+    {
+        return new Envelope(
+            subject: 'Notification of the results of the company you applied for on this system.',
+        );
+    }
+
+    /**
+     * Get the message content definition.
+     */
+    public function content(): Content
+    {
+        return new Content(
+            //view: 'view.name',
+            markdown: 'emails.actions.company',
+//            with: [
+//                'company' =>$this->company,
+//                'user' =>$this->user,
+//            ]
+        );
+    }
+
+    /**
+     * Get the attachments for the message.
+     *
+     * @return array<int, \Illuminate\Mail\Mailables\Attachment>
+     */
+    public function attachments(): array
+    {
+        return [];
+    }
+}

+ 20 - 0
app/Models/Enums/CompanyReviewStatus.php

@@ -0,0 +1,20 @@
+<?php
+/**
+ * Created by IntelliJ IDEA.
+ * User: kelyliang
+ * Date: 2024/6/27
+ * Time: 下午 02:50
+ */
+
+namespace App\Models\Enums;
+
+
+enum CompanyReviewStatus: string
+{
+    case WAIT = 'wait'; //未开始
+
+    case APPROVED = 'approved'; // 已批准
+
+    case REJECTED = 'rejected';
+
+}

+ 5 - 0
app/Models/Enums/FileObjectType.php

@@ -4,6 +4,7 @@ namespace App\Models\Enums;
 
 use App\Models\Action;
 use App\Models\Asset;
+use App\Models\Company;
 use App\Models\Container;
 use App\Models\Plan;
 use App\Models\Project;
@@ -26,6 +27,8 @@ enum FileObjectType: string
 
     case CONTAINER = "container";
 
+    case COMPANY = "company";
+
     public function modelBuilder(): \Illuminate\Database\Eloquent\Builder
     {
         return match ($this) {
@@ -36,6 +39,7 @@ enum FileObjectType: string
             self::ACTION => Action::query(),
             self::PLAN => Plan::query(),
             self::CONTAINER => Container::query(),
+            self::COMPANY => Company::query(),
         };
     }
 
@@ -49,6 +53,7 @@ enum FileObjectType: string
             self::ACTION => Action::query(),
             self::PLAN => Plan::query(),
             self::CONTAINER => Container::query()->allowed($id),
+            self::COMPANY => Company::query(),
         };
     }
 }

+ 4 - 1
app/Models/File.php

@@ -6,6 +6,7 @@ use App\Models\Scopes\CompanyScope;
 use Illuminate\Database\Eloquent\Factories\HasFactory;
 use Illuminate\Database\Eloquent\Model;
 use Illuminate\Database\Eloquent\SoftDeletes;
+use Illuminate\Support\Facades\Auth;
 
 class File extends Model
 {
@@ -15,7 +16,9 @@ class File extends Model
 
     protected static function booted(): void
     {
-        static::addGlobalScope(new CompanyScope);
+        if(Auth::check()&&!Auth::user()->super_admin){
+            static::addGlobalScope(new CompanyScope);
+        }
     }
 
     public function createdBy(): \Illuminate\Database\Eloquent\Relations\BelongsTo

+ 76 - 0
app/Services/File/Upload/CompanyUploadService.php

@@ -0,0 +1,76 @@
+<?php
+/**
+ * Created by IntelliJ IDEA.
+ * User: kelyliang
+ * Date: 2024/7/2
+ * Time: 下午 12:05
+ */
+
+namespace App\Services\File\Upload;
+
+
+use App\Http\Resources\API\FileUploadSuccessResource;
+use App\Models\File;
+use Illuminate\Http\Request;
+use Illuminate\Http\UploadedFile;
+
+class CompanyUploadService
+{
+    public function __construct(protected Request $request)
+    {
+
+    }
+
+    public function upload(): array
+    {
+        $items = [];
+        $fileNames = $this->request->get("file_names", []);
+        foreach ($this->request->file("files") as $index => $file) {
+
+            $item = $this->uploadFile($this->request, $file);
+            $item['file']['title'] = $fileNames[$index] ?? $item['file']['title'];
+
+            $items[] = $item;
+        }
+        $uploadedFiles = $this->storeFiles($items);
+
+        return $uploadedFiles;
+    }
+
+    protected function uploadFile(Request $request, UploadedFile $file): array
+    {
+        $extension = $file->getClientOriginalExtension() ? $file->getClientOriginalExtension(): pathinfo($file->getClientOriginalName(), PATHINFO_EXTENSION);
+
+        $pathname = $file->storeAs(
+            sprintf("c%s/%s/%s", uniqid(), $request->get("object_type"), date("Ymd")),
+            sprintf("%s.%s", md5(uniqid()), $extension)
+        );
+        throw_validation_if(! $pathname, "File upload failed.");
+
+        $data['file'] = [
+            'pathname' => $pathname,
+            'title' => $file->getClientOriginalName(),
+            'size' => $file->getSize(),
+            'extension' => $extension,
+            'company_id' => uniqid(),
+            'object_type' => $request->object_type,
+            'source' => $request->get("source", 1),
+        ];
+
+        return $data;
+    }
+
+
+    protected function storeFiles(array $items)
+    {
+        $uploadedFiles = [];
+        foreach ($items as $item) {
+            $fileInfo = $item['file'];
+            $file = File::query()->create($fileInfo);
+            $uploadedFiles[] = new FileUploadSuccessResource($file);
+        }
+
+        return $uploadedFiles;
+    }
+
+}

+ 31 - 0
database/migrations/2024_06_27_144414_add_review_status_and_exp_date_to_company.php

@@ -0,0 +1,31 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+return new class extends Migration
+{
+    /**
+     * Run the migrations.
+     */
+    public function up(): void
+    {
+        Schema::table('company', function (Blueprint $table) {
+            //
+            $table->string("review_status", 30)->nullable()->default(\App\Models\Enums\CompanyReviewStatus::WAIT->value);
+            $table->date("exp_date")->nullable();
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     */
+    public function down(): void
+    {
+        Schema::table('company', function (Blueprint $table) {
+            //
+            $table->dropColumn(['review_status','exp_date']);
+        });
+    }
+};

+ 24 - 0
resources/views/emails/actions/company.blade.php

@@ -0,0 +1,24 @@
+
+<x-mail::message>
+# Company Name: {{ $company->name }}
+
+## Status: {{$company->review_status}}
+
+## Note:
+
+    @if($company->review_status->value === "approved")
+
+###   Congratulations! The company you applied for has passed the background review.This audit is valid until :{{$company->exp_date}}<br>Initialize the account information as follows:<br><br>name:     {{$user->name}} <br>username:    {{$user->username}} <br>password:    admin@#123<br>
+###   Please change your password when logging in for the first time
+    @else
+
+###   Your company application was not approved.
+###   Reason for rejection: {{$rejectReason}}
+    @endif
+
+Thanks,<br>
+[Go to login]({{config('app.url')}})<br>
+From {{ config('app.name') }}
+
+</x-mail::message>
+

+ 9 - 1
routes/api.php

@@ -18,6 +18,9 @@ use App\Http\Controllers\API;
 Route::post("/login", [API\AuthController::class, "login"]);
 Route::post("/send-forget-password-email", [API\AuthController::class, "sendForgetPasswordEmail"]);
 Route::post("/reset-password", [API\AuthController::class, "resetPassword"]);
+//Route::post("register/company-user", [API\UserController::class, "registerCompanyUser"]);
+Route::post("register/company", [API\CompanyController::class, "registerCompany"]);
+Route::post("company-file-upload", [API\FileController::class, "companyUpload"]);
 //暂时为免登录
 Route::get("file/download/{uuid}/share-file", [API\FileController::class, "downloadShareFile"])
     ->name("file.download-share-file");
@@ -25,7 +28,7 @@ Route::get("file/download/{uuid}/share-file", [API\FileController::class, "downl
 
 
 
-Route::middleware(['auth:sanctum'])->group(function () {
+Route::middleware(['auth:sanctum','account.limit'])->group(function () {
     Route::post("/logout", [API\AuthController::class, "logout"]);
     Route::get("user/details", [API\UserController::class, 'details'])->name("user.details");
 
@@ -38,6 +41,8 @@ Route::middleware(['auth:sanctum'])->group(function () {
         Route::post("config/message-notification-setting", [API\ConfigController::class, "storeMessageNotificationSetting"])
             ->name("config.store-message-notification-setting");
 
+        Route::put("company/action", [API\CompanyController::class, "action"])->name("company.action");
+
         Route::apiResource("company", API\CompanyController::class)->only([
             'store', 'update', 'destroy'
         ]);
@@ -53,6 +58,9 @@ Route::middleware(['auth:sanctum'])->group(function () {
         Route::get("role/{role}/menus", [API\RoleController::class, "menus"])->name("role.menus");
 //        Route::patch("user/userInfo/{user_id}",[API\UserController::class, 'updateUserInfo'])->name('user.updateUserInfo');
 
+        Route::post("company/action",[API\CompanyController::class,"action"])->name("company.action");
+
+
     });
 
     Route::middleware(['permission'])->group(function() {