Skip to content

Commit

Permalink
Merge pull request #1 from functionofpwnosec/enhancements
Browse files Browse the repository at this point in the history
Laravel@secure_dev
  • Loading branch information
functionofpwnosec authored Oct 10, 2024
2 parents 2713359 + e591a17 commit 3bd61ad
Show file tree
Hide file tree
Showing 16 changed files with 508 additions and 2 deletions.
107 changes: 105 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,105 @@
# laravel-security-enhancements
This project is a simple Laravel application that comes with various security features to protect against common attacks such as SQL Injection, XSS, CSRF, and others. The project also comes with secure authentication features and user access rights management.
# Laravel Security Enhancements Project

## Deskripsi

Proyek ini merupakan aplikasi web yang dibangun menggunakan framework Laravel, yang dirancang untuk mendemonstrasikan berbagai fitur keamanan dan pengelolaan konten. Dalam dunia yang semakin terhubung, penting bagi pengembang untuk memahami dan menerapkan praktik keamanan terbaik untuk melindungi data pengguna dan mencegah serangan.

Aplikasi ini menawarkan fitur-fitur seperti pengelolaan artikel, komentar, pengaturan profil pengguna, dan notifikasi keamanan. Melalui aplikasi ini, pengguna dapat membuat, mengedit, dan menghapus artikel, serta menambahkan komentar pada artikel yang ada. Proyek ini juga dilengkapi dengan sistem autentikasi pengguna, yang memungkinkan pengguna untuk mendaftar, login, dan mengelola profil mereka.

Salah satu fitur unggulan dari aplikasi ini adalah pengiriman notifikasi kepada pengguna ketika ada login dari perangkat atau alamat IP baru, menambah lapisan keamanan tambahan untuk melindungi akun pengguna.

### Fitur Utama

- **Pengelolaan Pengguna:**
- Registrasi pengguna baru
- Login dan logout pengguna
- Pengaturan profil pengguna yang dapat diperbarui

- **Pengelolaan Artikel:**
- Membuat, mengedit, dan menghapus artikel
- Menampilkan daftar artikel dengan detail penulis

- **Komentar:**
- Menambahkan komentar pada artikel
- Menghapus komentar yang telah ditambahkan

- **Notifikasi Keamanan:**
- Mengirim notifikasi melalui email kepada pengguna saat login dari perangkat baru
- Mencatat alamat IP terakhir yang digunakan untuk login

### Teknologi yang Digunakan

- **Laravel**: Framework PHP untuk membangun aplikasi web.
- **MySQL**: Database untuk menyimpan data pengguna, artikel, dan komentar.
- **Bootstrap**: Framework CSS untuk mempercepat pengembangan antarmuka pengguna.
- **Composer**: Manajer paket untuk PHP yang digunakan untuk mengelola ketergantungan proyek.

### Instalasi

Untuk menginstal dan menjalankan proyek ini, ikuti langkah-langkah berikut:

1. **Klon Repository**

```bash
git clone https://github.com/username/repo-name.git
cd repo-name
```
2. Instal Ketergantungan
Pastikan Anda telah menginstal Composer, kemudian jalankan:
```
composer install
```
3. Konfigurasi Environment
Salin file `.env.example` ke `.env`:
```
cp .env.example .env
```
Kemudian, atur koneksi database Anda di file `.env`.

4. Migrasi Database
Jalankan migrasi untuk membuat tabel di database:
```
php artisan migrate
```
5. Menjalankan Aplikasi
Setelah semua konfigurasi selesai, Anda dapat menjalankan server lokal menggunakan perintah berikut:
```
php artisan serve
```
Akses aplikasi di `http://localhost:8000`.

## Kesimpulan
Proyek ini merupakan contoh penerapan prinsip keamanan dalam pengembangan aplikasi web menggunakan Laravel. Dengan menambahkan berbagai fitur seperti pengelolaan pengguna, artikel, komentar, dan notifikasi keamanan, proyek ini bertujuan untuk memberikan pemahaman yang lebih baik tentang bagaimana mengamankan aplikasi web dan melindungi data pengguna.

## Hak Cipta
Hak cipta sepenuhnya dimiliki oleh **PT. PwnOsec Technologies Ltd.** dengan semua hak yang terkait. Tidak ada bagian dari perangkat lunak ini, baik dalam bentuk kode sumber, dokumentasi, maupun komponen lainnya, yang boleh didistribusikan, dimodifikasi, atau digunakan untuk tujuan komersial tanpa persetujuan tertulis dari pemilik hak cipta.

### Tanggal Penerbitan
Hak cipta ini berlaku mulai dari tanggal penerbitan proyek ini, dan akan diperbarui secara berkala oleh **PT. PwnOsec Technologies Ltd.** untuk memastikan perlindungan hukum yang sesuai.

## Lisensi Penggunaan
Proyek ini dilisensikan di bawah model lisensi berikut:

1. **Penggunaan Komersial:**
Penggunaan komersial perangkat lunak ini hanya diizinkan bagi pihak-pihak yang telah mendapatkan lisensi resmi dari PT. PwnOsec Technologies Ltd.

2. **Penggunaan Pribadi:**
Anda diizinkan untuk mempelajari dan mengkloning proyek ini hanya untuk penggunaan pribadi dan edukasi. Penggunaan dalam skala komersial, redistribusi, atau penjualan kembali perangkat lunak ini memerlukan izin resmi.

3. **Modifikasi:**
Modifikasi diperbolehkan hanya untuk penggunaan internal dan pribadi. Setiap modifikasi yang dilakukan tidak boleh didistribusikan atau dijual tanpa persetujuan dari PT. PwnOsec Technologies Ltd.

## Kontak
Jika Anda memiliki pertanyaan terkait penggunaan, lisensi, atau memerlukan izin penggunaan komersial, silakan hubungi kami di:

- **Email:** [email protected]
- **Situs Web:** [www.pwnosec.com](http://www.pwnosec.com)
- **Alamat Kantor:**
PT. PwnOsec Technologies Ltd.
Jl. Keamanan Siber No. 123, Jakarta, Indonesia

---
Hak cipta © 2024 **PT. PwnOsec Technologies Ltd.**. Semua hak dilindungi undang-undang.



65 changes: 65 additions & 0 deletions app/Http/Controllers/ArticleController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<?php

namespace App\Http\Controllers;

use App\Models\Article;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class ArticleController extends Controller
{
public function index()
{
$articles = Article::with('user')->get();
return view('articles.index', compact('articles'));
}

public function create()
{
return view('articles.create');
}

public function store(Request $request)
{
$request->validate([
'title' => 'required|string|max:255',
'content' => 'required|string',
]);

Article::create([
'title' => $request->title,
'content' => $request->content,
'user_id' => Auth::id(),
]);

return redirect()->route('articles.index');
}

public function edit(Article $article)
{
return view('articles.edit', compact('article'));
}

public function update(Request $request, Article $article)
{
$request->validate([
'title' => 'required|string|max:255',
'content' => 'required|string',
]);

$article->update($request->only('title', 'content'));

return redirect()->route('articles.index');
}

public function show(Article $article)
{
return view('articles.show', compact('article'));
}

public function destroy(Article $article)
{
$article->delete();
return redirect()->route('articles.index');
}
}
20 changes: 20 additions & 0 deletions app/Http/Controllers/AuthController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use App\Notifications\NewDeviceLogin;

public function login(Request $request)
{
$credentials = $request->only('email', 'password');

if (Auth::attempt($credentials)) {
// Kirim notifikasi jika login dari IP baru
if (session()->get('last_ip_address') !== $request->ip()) {
auth()->user()->notify(new NewDeviceLogin($request->ip()));
}

session(['last_ip_address' => $request->ip()]); // Simpan IP terakhir
return redirect()->route('welcome');
}

return back()->withErrors([
'email' => 'The provided credentials do not match our records.',
]);
}
32 changes: 32 additions & 0 deletions app/Http/Controllers/CommentController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

namespace App\Http\Controllers;

use App\Models\Comment;
use App\Models\Article;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class CommentController extends Controller
{
public function store(Request $request, Article $article)
{
$request->validate([
'content' => 'required|string',
]);

Comment::create([
'content' => $request->content,
'article_id' => $article->id,
'user_id' => Auth::id(),
]);

return redirect()->route('articles.show', $article);
}

public function destroy(Comment $comment)
{
$comment->delete();
return back();
}
}
17 changes: 17 additions & 0 deletions app/Http/Controllers/UserController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
public function edit()
{
return view('user.edit', ['user' => auth()->user()]);
}

public function update(Request $request)
{
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255',
]);

$user = auth()->user();
$user->update($request->only('name', 'email'));

return redirect()->route('profile')->with('success', 'Profile updated successfully.');
}
23 changes: 23 additions & 0 deletions app/Models/Article.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Article extends Model
{
use HasFactory;

protected $fillable = ['title', 'content', 'user_id'];

public function user()
{
return $this->belongsTo(User::class);
}

public function comments()
{
return $this->hasMany(Comment::class);
}
}
23 changes: 23 additions & 0 deletions app/Models/Comment.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Comment extends Model
{
use HasFactory;

protected $fillable = ['content', 'article_id', 'user_id'];

public function article()
{
return $this->belongsTo(Article::class);
}

public function user()
{
return $this->belongsTo(User::class);
}
}
33 changes: 33 additions & 0 deletions app/Notifications/NewDeviceLogin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace App\Notifications;

use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;

class NewDeviceLogin extends Notification
{
use Queueable;

protected $ipAddress;

public function __construct($ipAddress)
{
$this->ipAddress = $ipAddress;
}

public function via($notifiable)
{
return ['mail'];
}

public function toMail($notifiable)
{
return (new MailMessage)
->greeting('Hello!')
->line('A login was detected from a new device.')
->line('IP Address: ' . $this->ipAddress)
->line('If this was you, you can ignore this message. If not, please secure your account.');
}
}
24 changes: 24 additions & 0 deletions database/migrations/2024_10_11_000001_create_articles_table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateArticlesTable extends Migration
{
public function up()
{
Schema::create('articles', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('content');
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->timestamps();
});
}

public function down()
{
Schema::dropIfExists('articles');
}
}
24 changes: 24 additions & 0 deletions database/migrations/2024_10_11_000002_create_comments_table.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateCommentsTable extends Migration
{
public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->id();
$table->text('content');
$table->foreignId('article_id')->constrained()->onDelete('cascade');
$table->foreignId('user_id')->constrained()->onDelete('cascade');
$table->timestamps();
});
}

public function down()
{
Schema::dropIfExists('comments');
}
}
15 changes: 15 additions & 0 deletions resources/views/articles/create.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!DOCTYPE html>
<html>
<head>
<title>Create Article</title>
</head>
<body>
<h1>Create Article</h1>
<form method="POST" action="{{ route('articles.store') }}">
@csrf
<input type="text" name="title" required placeholder="Title">
<textarea name="content" required placeholder="Content"></textarea>
<button type="submit">Submit</button>
</form>
</body>
</html>
Loading

0 comments on commit 3bd61ad

Please sign in to comment.