'''
Item: Safety Jwt Password Mananer
Time: 2025-10-23
Author: 1ceLAND
'''

from flask import Flask, request, redirect, url_for, render_template
import jwt
import uuid
import os

from werkzeug.security import generate_password_hash, check_password_hash


app = Flask(__name__)
app.config['SECRET_KEY'] = '0f3cbb44-f199-4d34-ade9-1545c0972648'

accounts_usernames = []
accounts = {} # help save accounts instead sqlite

# instead of sqliteeee
user_passwords = {}

def check_username(new_username):
    if new_username in accounts_usernames:
        return True
    return False

def check_login(username, password):
    if username not in accounts:
        return False
    return check_password_hash(accounts[username], password)

def insert_account(new_username, new_password_hash):
    try:
        accounts_usernames.append(new_username)
        accounts[new_username] = new_password_hash
        user_passwords[new_username] = []
        return True
    except:
        return False

def create_token(username):
    # create jwt
    payload = {
        'username': username,
    }
    token = jwt.encode(payload, app.config['SECRET_KEY'], algorithm='HS256')
    if isinstance(token, bytes):
        token = token.decode('utf-8')
    return token

def verify_token(token):
    try:
        payload = jwt.decode(token, app.config['SECRET_KEY'], algorithms=['HS256'])
        return payload['username']
    except:
        return None

def login_required(f):
    def decorated(*args, **kwargs):
        token = request.cookies.get('token')
        if not token or not verify_token(token):
            return redirect(url_for('login'))
        return f(*args, **kwargs)
    decorated.__name__ = f.__name__
    return decorated

def add_password_item(username, website, site_username, password, notes=""):
    try:
        password_item = {
            'id': str(uuid.uuid4()),
            'website': website,
            'username': site_username,
            'password': password,
            'notes': notes,
        }
        user_passwords[username].append(password_item)
        return True
    except:
        return False


def delete_password_item(username, item_id):
    # delete ...
    try:
        user_passwords[username] = [item for item in user_passwords[username] if item['id'] != item_id]
        return True
    except:
        return False
        
def get_user_passwords(username):
    # get all password_item of someone ...
    return user_passwords.get(username, [])

@app.route('/')
def index():
    return redirect(url_for('login'))

@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']
        
        user_exists = check_username(username)
        if user_exists:
            return render_template('register.html', error_msg="User Already Existed!")

        password_hash = generate_password_hash(password)
        insert_account(username, password_hash)
        
        return redirect(url_for('login'))
    
    return render_template('register.html')

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        username = request.form['username']
        password = request.form['password']

        user_exists = check_username(username)
        if user_exists == False:
            return render_template('login.html', error_msg='Username or Password Wrong!')
        
        if check_login(username, password):
            token = create_token(username)
            response = redirect(url_for('dashboard'))
            response.set_cookie('token', token, httponly=True)
            return response
        else:
            return render_template('login.html', error_msg='Username or Password Wrong!')
        
    return render_template('login.html')

@app.route('/logout')
def logout():
    response = redirect(url_for('login'))
    response.delete_cookie('token')
    return response

@app.route('/dashboard')
@login_required
def dashboard():
    username = verify_token(request.cookies.get('token'))
    passwords = get_user_passwords(username)
    return render_template('dashboard.html',
                           username=username,
                           passwords=passwords)
    
@app.route('/add_password', methods=['POST'])
@login_required
def add_password():
    username = verify_token(request.cookies.get('token'))
    website = request.form['website']
    site_username = request.form['site_username']
    password = request.form['password']
    notes = request.form.get('notes', '')
    
    if add_password_item(username, website, site_username, password, notes):
        return redirect(url_for('dashboard'))
    else:
        return render_template('dashboard.html', 
                             username=username,
                             passwords=get_user_passwords(username),
                             error_msg="Add password error")
        
@app.route('/delete_password/<item_id>')
@login_required
def delete_password(item_id):
    username = verify_token(request.cookies.get('token'))
    
    if delete_password_item(username, item_id):
        return redirect(url_for('dashboard'))
    else:
        return render_template('dashboard.html', 
                             username=username,
                             passwords=get_user_passwords(username),
                             error_msg="Delete password error")

if __name__ == '__main__':
    admin_password = str(uuid.uuid4())
    insert_account('admin', generate_password_hash(admin_password))
    
    # flag in admin account ! ^-^
    for path in ['/flag', './flag.txt']:
        try:
            if os.path.exists(path) and os.path.isfile(path):
                with open(path, 'rb') as f:
                    raw = f.read()
                if raw:
                    content = raw.decode('utf-8', errors='replace').strip()
                    add_password_item('admin',
                                      website='seeded-flag',
                                      site_username='flag-file',
                                      password=content,
                                      notes=f'seeded from {path}')
                break
        except:
            pass
    app.run(debug=False, host='0.0.0.0')