update api

This commit is contained in:
2026-02-20 17:04:36 +07:00
parent 66c8bb6810
commit 1dfcf9b2f5
22 changed files with 655 additions and 13 deletions
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace App\Enums;
enum KondisiTanaman: string
{
case SEHAT = 'sehat';
case SAKIT = 'sakit';
case MATI = 'mati';
}
+11
View File
@@ -0,0 +1,11 @@
<?php
namespace App\Enums;
enum Role: string
{
case SUPER_ADMIN = 'super_admin';
case ADMIN = 'admin';
case FASILITATOR = 'fasilitator';
case PETANI = 'petani';
}
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace App\Enums;
enum StatusLahan: string
{
case SENDIRI = 'sendiri';
case SEWA = 'sewa';
case ADAT = 'adat';
}
@@ -6,6 +6,10 @@ use App\Http\Controllers\Controller;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Auth;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Hash;
use App\Models\User;
use App\Models\Profile;
class AuthController extends Controller class AuthController extends Controller
{ {
@@ -33,6 +37,46 @@ class AuthController extends Controller
]); ]);
} }
public function signup(Request $request): JSONResponse
{
$credentials = $request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'email'],
'password' => ['required', 'string', 'min:8', 'confirmed'],
'role' => ['string'],
]);
$user = User::create([
'name' => $credentials['name'],
'email' => $credentials['email'],
'password' => Hash::make($credentials['password']),
'role' => $credentials['role'],
]);
$profile = Profile::create([
'nama' => $credentials['name'],
'email' => $credentials['email'],
'role' => $credentials['role'],
'user_id' => $user->id,
]);
if (!Auth::attempt($credentials)) {
return response()->json([
'message' => 'Email dan/atau password tidak sesuai'
], 401);
}
$user = Auth::user();
$user->tokens()->delete();
$token = $user->createToken('mobile-token')->plainTextToken;
return response()->json([
'access_token' => $token,
'token_type' => 'Bearer',
]);
}
public function me(Request $request): JSONResponse public function me(Request $request): JSONResponse
{ {
return response()->json($request->user()); return response()->json($request->user());
@@ -0,0 +1,140 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Gate;
use App\Models\Map\Lahan;
class LahanController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index(): JsonResponse
{
Gate::authorize('petani');
$user = Auth::user();
$profile = $user->profile;
$listLahan = Lahan::where('profile_id', $profile->id)->get();
return response()->json($listLahan);
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request): JsonResponse
{
Gate::authorize('petani');
$user = Auth::user();
$profile = $user->profile;
$validated = $request->validate([
'nama' => ['required', 'string', 'max:255'],
'status_kepemilikan' => ['required', 'string'],
'desa_kelurahan_id' => ['numeric'],
'path' => ['string'],
'luas_lahan' => ['numeric'],
]);
$lahan = Lahan::create([
'nama' => $validated['nama'],
'status_kepemilikan' => $validated['status_kepemilikan'],
'profile_id' => $profile->id,
'desa_kelurahan_id' => $validated['desa_kelurahan_id'] ?? null,
'path' => $validated['path'] ?? null,
'luas_lahan' => $validated['luas_lahan'] ?? null,
]);
return response()->json($lahan, 201);
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
Gate::authorize('petani');
$lahan = Lahan::findOrFail($id);
return response()->json($lahan);
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
Gate::authorize('petani');
$lahan = Lahan::findOrFail($id);
$validated = $request->validate([
'nama' => ['required', 'string', 'max:255'],
'status_kepemilikan' => ['required', 'string'],
'desa_kelurahan_id' => ['numeric'],
'path' => ['string'],
'luas_lahan' => ['numeric'],
]);
$lahan->update($validated);
return response()->json($lahan);
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
Gate::authorize('petani');
$lahan = Lahan::findOrFail($id);
$lahan->delete();
return response()->json(null, 204);
}
public function batchUpsert(Request $request): JsonResponse
{
Gate::authorize('petani');
$user = Auth::user();
$profile = $user->profile;
$validated = $request->validate([
'lahans' => ['required', 'array'],
'lahans.*.id' => ['numeric'],
'lahans.*.nama' => ['required', 'string', 'max:255'],
'lahans.*.status_kepemilikan' => ['required', 'numeric'],
'lahans.*.desa_kelurahan_id' => ['numeric'],
'lahans.*.path' => ['string'],
'lahans.*.luas_lahan' => ['numeric'],
]);
$lahans = [];
foreach ($validated['lahans'] as $lahan) {
$lahans[] = [
'id' => $lahan['id'] ?? null,
'nama' => $lahan['nama'],
'status_kepemilikan' => $lahan['status_kepemilikan'],
'profile_id' => $profile->id,
'desa_kelurahan_id' => $lahan['desa_kelurahan_id'] ?? null,
'path' => $lahan['path'] ?? null,
'luas_lahan' => $lahan['luas_lahan'] ?? null,
];
}
Lahan::upsert($lahans, ['id'], ['nama', 'status_kepemilikan', 'profile_id', 'desa_kelurahan_id', 'path', 'luas_lahan']);
return response()->json(null, 204);
}
}
@@ -0,0 +1,78 @@
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Profile;
use Illuminate\Support\Facades\Auth;
class ProfileController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
//
}
/**
* Show the form for creating a new resource.
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*/
public function show()
{
$profile = Profile::where('user_id', Auth::id())->first();
return response()->json($profile);
}
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request)
{
$validated = $request->validate([
'nama' => ['required', 'string', 'max:255'],
'email' => ['required', 'email'],
'telepon' => ['nullable', 'string'],
'alamat' => ['nullable', 'string'],
]);
$profile = Profile::where('user_id', Auth::id())->first();
$profile->update($validated);
return response()->json($profile);
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}
+17
View File
@@ -0,0 +1,17 @@
<?php
namespace App\Models\Komoditas;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Komoditas extends Model
{
use SoftDeletes;
protected $table = 'master_komoditas';
protected $fillable = [
'nama'
];
}
+38
View File
@@ -0,0 +1,38 @@
<?php
namespace App\Models\Map;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\HasMany;
class Lahan extends Model
{
use SoftDeletes;
protected $table = 'map_lahan';
protected $fillable = [
'nama',
'status_kepemilikan',
'profile_id',
'desa_kelurahan_id',
'path',
'luas_lahan',
'created_by',
'updated_by',
'deleted_by',
];
protected function casts(): array
{
return [
'status_kepemilikan' => \App\Enums\StatusLahan::class,
];
}
public function tanaman(): HasMany
{
return $this->hasMany(Tanaman::class, 'lahan_id');
}
}
+25
View File
@@ -0,0 +1,25 @@
<?php
namespace App\Models\Map;
use Illuminate\Database\Eloquent\Model;
class Tanaman extends Model
{
use SoftDeletes;
protected $table = 'map_tanaman';
protected $fillable = [
'nama',
'komoditas_id',
'profile_id',
'lahan_id',
'latitude',
'longitude',
'kondisi_tanaman',
'created_by',
'updated_by',
'deleted_by',
];
}
+22
View File
@@ -0,0 +1,22 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Profile extends Model
{
use SoftDeletes;
protected $fillable = [
'user_id',
'role',
'nama',
'email',
'telepon',
'alamat',
'kk',
'ktp',
];
}
+11
View File
@@ -6,15 +6,20 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable; use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Laravel\Sanctum\HasApiTokens; use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable class User extends Authenticatable
{ {
use HasFactory, Notifiable, HasApiTokens, SoftDeletes;
protected $fillable = [ protected $fillable = [
'name', 'name',
'email', 'email',
'password', 'password',
'email_verified_at', 'email_verified_at',
'role',
]; ];
protected $hidden = [ protected $hidden = [
@@ -27,6 +32,12 @@ class User extends Authenticatable
return [ return [
'email_verified_at' => 'datetime', 'email_verified_at' => 'datetime',
'password' => 'hashed', 'password' => 'hashed',
'role' => \App\Enums\Role::class,
]; ];
} }
protected function profile(): HasOne
{
return $this->hasOne(\App\Models\Profile::class);
}
} }
+3
View File
@@ -3,9 +3,12 @@
namespace App\Models\wilayah; namespace App\Models\wilayah;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class DesaKelurahan extends Model class DesaKelurahan extends Model
{ {
use SoftDeletes;
protected $table = 'master_desa_kelurahan'; protected $table = 'master_desa_kelurahan';
protected $fillable = [ protected $fillable = [
+3
View File
@@ -3,9 +3,12 @@
namespace App\Models\Wilayah; namespace App\Models\Wilayah;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class KabupatenKota extends Model class KabupatenKota extends Model
{ {
use SoftDeletes;
protected $table = 'master_kabupaten_kota'; protected $table = 'master_kabupaten_kota';
protected $fillable = [ protected $fillable = [
+3
View File
@@ -3,9 +3,12 @@
namespace App\Models\Wilayah; namespace App\Models\Wilayah;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Kecamatan extends Model class Kecamatan extends Model
{ {
use SoftDeletes;
protected $table = 'master_kecamatan'; protected $table = 'master_kecamatan';
protected $fillable = [ protected $fillable = [
+3
View File
@@ -3,9 +3,12 @@
namespace App\Models\Wilayah; namespace App\Models\Wilayah;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Provinsi extends Model class Provinsi extends Model
{ {
use SoftDeletes;
protected $table = 'master_provinsi'; protected $table = 'master_provinsi';
protected $fillable = [ protected $fillable = [
+18 -1
View File
@@ -3,6 +3,9 @@
namespace App\Providers; namespace App\Providers;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Gate;
use App\Models\User;
use App\Enums\Role;
class AppServiceProvider extends ServiceProvider class AppServiceProvider extends ServiceProvider
{ {
@@ -19,6 +22,20 @@ class AppServiceProvider extends ServiceProvider
*/ */
public function boot(): void public function boot(): void
{ {
// Gate::define('super-admin', function (User $user) {
return $user->role === Role::SUPER_ADMIN;
});
Gate::define('admin', function (User $user) {
return $user->role === Role::ADMIN;
});
Gate::define('fasilitator', function (User $user) {
return $user->role === Role::FASILITATOR;
});
Gate::define('petani', function (User $user) {
return $user->role === Role::PETANI;
});
} }
} }
+2
View File
@@ -3,6 +3,8 @@
use Illuminate\Foundation\Application; use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Exceptions; use Illuminate\Foundation\Configuration\Exceptions;
use Illuminate\Foundation\Configuration\Middleware; use Illuminate\Foundation\Configuration\Middleware;
use Illuminate\Http\Request;
use Illuminate\Auth\AuthenticationException;
return Application::configure(basePath: dirname(__DIR__)) return Application::configure(basePath: dirname(__DIR__))
->withRouting( ->withRouting(
@@ -15,6 +15,7 @@ return new class extends Migration
$table->timestamp('email_verified_at')->nullable(); $table->timestamp('email_verified_at')->nullable();
$table->string('password'); $table->string('password');
$table->rememberToken(); $table->rememberToken();
$table->string('role')->nullable();
$table->foreignId('created_by')->nullable()->constrained('users')->onDelete('set null'); $table->foreignId('created_by')->nullable()->constrained('users')->onDelete('set null');
$table->foreignId('updated_by')->nullable()->constrained('users')->onDelete('set null'); $table->foreignId('updated_by')->nullable()->constrained('users')->onDelete('set null');
$table->foreignId('deleted_by')->nullable()->constrained('users')->onDelete('set null'); $table->foreignId('deleted_by')->nullable()->constrained('users')->onDelete('set null');
@@ -22,16 +23,16 @@ return new class extends Migration
$table->softDeletes(); $table->softDeletes();
}); });
Schema::create('user_roles', function (Blueprint $table) { // Schema::create('user_roles', function (Blueprint $table) {
$table->id(); // $table->id();
$table->foreignId('user_id')->unique()->constrained('users')->onDelete('cascade'); // $table->foreignId('user_id')->unique()->constrained('users')->onDelete('cascade');
$table->enum('role_name', ['Super Admin', 'Admin', 'Koordinator', 'Penyuluh', 'Pendamping', 'Petani'])->default('Petani'); // $table->enum('role_name', ['Super Admin', 'Admin', 'Koordinator', 'Penyuluh', 'Pendamping', 'Petani'])->default('Petani');
$table->foreignId('created_by')->nullable()->constrained('users')->onDelete('set null'); // $table->foreignId('created_by')->nullable()->constrained('users')->onDelete('set null');
$table->foreignId('updated_by')->nullable()->constrained('users')->onDelete('set null'); // $table->foreignId('updated_by')->nullable()->constrained('users')->onDelete('set null');
$table->foreignId('deleted_by')->nullable()->constrained('users')->onDelete('set null'); // $table->foreignId('deleted_by')->nullable()->constrained('users')->onDelete('set null');
$table->timestamps(); // $table->timestamps();
$table->softDeletes(); // $table->softDeletes();
}); // });
Schema::create('password_reset_tokens', function (Blueprint $table) { Schema::create('password_reset_tokens', function (Blueprint $table) {
$table->string('email')->primary(); $table->string('email')->primary();
@@ -52,7 +53,7 @@ return new class extends Migration
public function down(): void public function down(): void
{ {
Schema::dropIfExists('users'); Schema::dropIfExists('users');
Schema::dropIfExists('user_roles'); // Schema::dropIfExists('user_roles');
Schema::dropIfExists('password_reset_tokens'); Schema::dropIfExists('password_reset_tokens');
Schema::dropIfExists('sessions'); Schema::dropIfExists('sessions');
} }
@@ -0,0 +1,91 @@
<?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::create('adat', function (Blueprint $table) {
$table->id();
$table->string('nama')->nullable();
$table->foreignId('desa_kelurahan_id')->nullable()->constrained('master_desa_kelurahan');
$table->foreignId('created_by')->nullable()->constrained('users')->onDelete('set null');
$table->foreignId('updated_by')->nullable()->constrained('users')->onDelete('set null');
$table->foreignId('deleted_by')->nullable()->constrained('users')->onDelete('set null');
$table->timestamps();
$table->softDeletes();
});
Schema::create('keluarga', function (Blueprint $table) {
$table->id();
$table->string('kk')->nullable();
$table->foreignId('adat_id')->nullable()->constrained('adat');
$table->foreignId('desa_kelurahan_id')->nullable()->constrained('master_desa_kelurahan');
$table->string('path_kk', 500)->nullable();
$table->string('file_kk')->nullable();
$table->foreignId('created_by')->nullable()->constrained('users')->onDelete('set null');
$table->foreignId('updated_by')->nullable()->constrained('users')->onDelete('set null');
$table->foreignId('deleted_by')->nullable()->constrained('users')->onDelete('set null');
$table->timestamps();
$table->softDeletes();
});
Schema::create('profiles', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')->constrained();
$table->string('role')->nullable();
$table->string('nama');
$table->string('email');
$table->string('telepon')->nullable();
$table->string('alamat')->nullable();
$table->string('kk')->nullable();
$table->string('ktp')->nullable();
$table->foreignId('desa_kelurahan_id')->nullable()->constrained('master_desa_kelurahan');
$table->string('path_kk', 500)->nullable();
$table->string('file_kk')->nullable();
$table->string('path_ktp', 500)->nullable();
$table->string('file_ktp')->nullable();
$table->foreignId('keluarga_id')->nullable()->constrained('keluarga')->onDelete('set null');
$table->foreignId('created_by')->nullable()->constrained('users')->onDelete('set null');
$table->foreignId('updated_by')->nullable()->constrained('users')->onDelete('set null');
$table->foreignId('deleted_by')->nullable()->constrained('users')->onDelete('set null');
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('profiles');
Schema::dropIfExists('keluarga');
Schema::dropIfExists('adat');
}
};
@@ -0,0 +1,34 @@
<?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::create('master_komoditas', function (Blueprint $table) {
$table->id();
$table->string('nama');
$table->foreignId('created_by')->nullable()->constrained('users')->onDelete('set null');
$table->foreignId('updated_by')->nullable()->constrained('users')->onDelete('set null');
$table->foreignId('deleted_by')->nullable()->constrained('users')->onDelete('set null');
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('master_komoditas');
}
};
@@ -0,0 +1,66 @@
<?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::create('map_lahan', function (Blueprint $table) {
$table->id();
$table->string('nama');
$table->string('status_kepemilikan');
$table->foreignId('profile_id')->constrained('profiles');
$table->foreignId('keluarga_pengelola_id')->nullable()->constrained('keluarga')->onDelete('set null');
$table->foreignId('adat_pemilik_id')->nullable()->constrained('keluarga')->onDelete('set null');
$table->foreignId('desa_kelurahan_id')->nullable()->constrained('master_desa_kelurahan');
$table->text('path')->nullable();
$table->integer('luas_lahan')->nullable();
$table->foreignId('created_by')->nullable()->constrained('users')->onDelete('set null');
$table->foreignId('updated_by')->nullable()->constrained('users')->onDelete('set null');
$table->foreignId('deleted_by')->nullable()->constrained('users')->onDelete('set null');
$table->timestamps();
$table->softDeletes();
});
Schema::create('map_tanaman', function (Blueprint $table) {
$table->id();
$table->string('nama');
$table->foreignId('komoditas_id')->constrained('master_komoditas')->onDelete('set null');
$table->foreignId('profile_id')->constrained('profiles')->onDelete('set null');
$table->foreignId('lahan_id')->constrained('map_lahan')->onDelete('set null');
$table->float('latitude')->nullable();
$table->float('longitude')->nullable();
$table->string('kondisi_tanaman')->nullable();
$table->foreignId('created_by')->nullable()->constrained('users')->onDelete('set null');
$table->foreignId('updated_by')->nullable()->constrained('users')->onDelete('set null');
$table->foreignId('deleted_by')->nullable()->constrained('users')->onDelete('set null');
$table->timestamps();
$table->softDeletes();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('map_tanaman');
Schema::dropIfExists('map_lahan');
}
};
+14 -1
View File
@@ -3,7 +3,9 @@
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
Route::post('/auth/login', [\App\Http\Controllers\Api\AuthController::class, 'login']); Route::post('/auth/login', [\App\Http\Controllers\Api\AuthController::class, 'login'])
->middleware('throttle:5,1');
Route::post('/auth/signup', [\App\Http\Controllers\Api\AuthController::class, 'signup']);
Route::get('/user', function (Request $request) { Route::get('/user', function (Request $request) {
return $request->user(); return $request->user();
@@ -15,4 +17,15 @@ Route::middleware('auth:sanctum')
->group(function () { ->group(function () {
Route::get('/me', [\App\Http\Controllers\Api\AuthController::class, 'me']); Route::get('/me', [\App\Http\Controllers\Api\AuthController::class, 'me']);
Route::post('/logout', [\App\Http\Controllers\Api\AuthController::class, 'logout']); Route::post('/logout', [\App\Http\Controllers\Api\AuthController::class, 'logout']);
Route::get('/profile', [\App\Http\Controllers\Api\ProfileController::class, 'show']);
Route::put('/profile', [\App\Http\Controllers\Api\ProfileController::class, 'update']);
});
Route::middleware('auth:sanctum')
->name('map.')
->prefix('map')
->group(function () {
Route::apiResource('/lahan', \App\Http\Controllers\Api\LahanController::class)->except(['create', 'edit']);
}); });