Force7 / app.py
zetarmany's picture
Update app.py
fdd0871 verified
# app.py
import os
from flask import Flask, render_template, request, redirect, url_for, flash, jsonify, send_file
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from werkzeug.security import generate_password_hash, check_password_hash
from werkzeug.utils import secure_filename
from datetime import datetime
app = Flask(__name__)
app.config['SECRET_KEY'] = 'angkatan-rahasia-2024-2026'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///gallery.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['UPLOAD_FOLDER'] = 'static/uploads'
app.config['MAX_CONTENT_LENGTH'] = 50 * 1024 * 1024
# Buat folder upload
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
# Database
db = SQLAlchemy(app)
# Login manager
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login' # Penting!
# Models
class User(UserMixin, db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
password_hash = db.Column(db.String(200), nullable=False)
is_admin = db.Column(db.Boolean, default=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
def set_password(self, password):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
class Photo(db.Model):
__tablename__ = 'photos'
id = db.Column(db.Integer, primary_key=True)
filename = db.Column(db.String(200), nullable=False)
caption = db.Column(db.String(500))
upload_date = db.Column(db.DateTime, default=datetime.utcnow)
uploader_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
likes_count = db.Column(db.Integer, default=0)
uploader = db.relationship('User', backref='photos')
likes = db.relationship('Like', backref='photo', cascade='all, delete-orphan')
class Like(db.Model):
__tablename__ = 'likes'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
photo_id = db.Column(db.Integer, db.ForeignKey('photos.id'), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
__table_args__ = (db.UniqueConstraint('user_id', 'photo_id'),)
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
# CREATE ADMIN USERS (11 admin)
with app.app_context():
db.create_all()
print("✅ Database siap!")
admins = [
{'username': 'Hilbraaaam', 'password': 'Ketua Angkatan 24-26'},
{'username': 'Hudzaifahh', 'password': 'Wakil ketua Angkatan 24-26'},
{'username': 'Rafasyahh', 'password': 'Humas Kesayangan'},
{'username': 'Elazzam', 'password': 'Eos 800 D'},
{'username': 'Azzam Diq', 'password': 'Shidiq'},
{'username': 'Dzikrii', 'password': 'Bayar woe'},
{'username': 'Ibrahim', 'password': 'Mboh'},
{'username': 'Yusupp', 'password': 'Bangun'},
{'username': 'Azzam JR', 'password': 'Saturn'},
{'username': 'MK Azzam', 'password': 'Aneka Gold'},
{'username': 'Sami abd', 'password': 'TamTam'}
]
for admin_data in admins:
existing = User.query.filter_by(username=admin_data['username']).first()
if not existing:
admin = User(username=admin_data['username'], is_admin=True)
admin.set_password(admin_data['password'])
db.session.add(admin)
print(f"✓ Admin: {admin_data['username']}")
db.session.commit()
print(f"✅ Total admin: {User.query.filter_by(is_admin=True).count()}")
# ROUTES - SEDERHANA SAJA
@app.route('/')
def index():
photos = Photo.query.order_by(Photo.upload_date.desc()).all()
trending = Photo.query.order_by(Photo.likes_count.desc()).limit(3).all()
return render_template('index.html', photos=photos, trending=trending)
@app.route('/login', methods=['GET', 'POST'])
def login():
# Kalau sudah login, redirect ke home
if current_user.is_authenticated:
return redirect(url_for('index'))
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
user = User.query.filter_by(username=username).first()
if user and user.check_password(password):
login_user(user)
flash('Login berhasil!', 'success')
# Redirect berdasarkan role
if user.is_admin:
return redirect(url_for('admin'))
return redirect(url_for('index'))
else:
flash('Username atau password salah!', 'error')
return render_template('login.html')
@app.route('/logout')
def logout():
logout_user()
flash('Anda telah logout', 'info')
return redirect(url_for('index'))
@app.route('/admin')
def admin():
# Proteksi manual
if not current_user.is_authenticated:
flash('Silakan login dulu!', 'warning')
return redirect(url_for('login'))
if not current_user.is_admin:
flash('Halaman khusus admin!', 'error')
return redirect(url_for('index'))
photos = Photo.query.order_by(Photo.upload_date.desc()).all()
return render_template('admin.html', photos=photos)
@app.route('/upload', methods=['POST'])
def upload():
# Proteksi manual
if not current_user.is_authenticated or not current_user.is_admin:
flash('Akses ditolak!', 'error')
return redirect(url_for('index'))
if 'photo' not in request.files:
flash('Pilih file dulu!', 'error')
return redirect(url_for('admin'))
file = request.files['photo']
caption = request.form.get('caption', '')
if file.filename == '':
flash('Pilih file dulu!', 'error')
return redirect(url_for('admin'))
# Simpan file
filename = secure_filename(file.filename)
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S_')
filename = timestamp + filename
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
# Simpan ke DB
photo = Photo(filename=filename, caption=caption, uploader_id=current_user.id)
db.session.add(photo)
db.session.commit()
flash('Foto berhasil diupload!', 'success')
return redirect(url_for('admin'))
@app.route('/delete/<int:photo_id>')
def delete(photo_id):
# Proteksi manual
if not current_user.is_authenticated or not current_user.is_admin:
flash('Akses ditolak!', 'error')
return redirect(url_for('index'))
photo = Photo.query.get(photo_id)
if photo:
# Hapus file
filepath = os.path.join(app.config['UPLOAD_FOLDER'], photo.filename)
if os.path.exists(filepath):
os.remove(filepath)
db.session.delete(photo)
db.session.commit()
flash('Foto dihapus!', 'success')
return redirect(url_for('admin'))
@app.route('/like/<int:photo_id>', methods=['POST'])
def like(photo_id):
if not current_user.is_authenticated:
return jsonify({'error': 'Login dulu'}), 401
photo = Photo.query.get(photo_id)
if not photo:
return jsonify({'error': 'Foto tidak ada'}), 404
like = Like.query.filter_by(user_id=current_user.id, photo_id=photo_id).first()
if like:
db.session.delete(like)
photo.likes_count -= 1
liked = False
else:
like = Like(user_id=current_user.id, photo_id=photo_id)
db.session.add(like)
photo.likes_count += 1
liked = True
db.session.commit()
return jsonify({'liked': liked, 'likes': photo.likes_count})
@app.route('/download/<int:photo_id>')
def download(photo_id):
photo = Photo.query.get(photo_id)
if photo:
filepath = os.path.join(app.config['UPLOAD_FOLDER'], photo.filename)
if os.path.exists(filepath):
return send_file(filepath, as_attachment=True, download_name=photo.filename)
flash('File tidak ada!', 'error')
return redirect(url_for('index'))
@app.route('/slideshow')
def slideshow():
photos = Photo.query.order_by(Photo.upload_date.desc()).limit(10).all()
return jsonify([{'filename': p.filename} for p in photos])
@app.route('/cek_admin')
def cek_admin():
admins = User.query.filter_by(is_admin=True).all()
return jsonify({
'total': len(admins),
'usernames': [a.username for a in admins]
})
if __name__ == '__main__':
port = int(os.environ.get('PORT', 7860))
app.run(host='0.0.0.0', port=port, debug=False)