password requirements and opengraph for discord,slack etc
This commit is contained in:
parent
79d0adfcf8
commit
740300edaf
66
app.py
66
app.py
@ -264,20 +264,27 @@ def redirect_vanity(vanity, password=None):
|
|||||||
return render_template('password_prompt.html', vanity=vanity, error=None)
|
return render_template('password_prompt.html', vanity=vanity, error=None)
|
||||||
|
|
||||||
if content_type == 'url':
|
if content_type == 'url':
|
||||||
return redirect(content_data)
|
return render_template('og_shorturl.html', long_url=content_data, username=username, created_at=created_at)
|
||||||
elif content_type == 'file':
|
elif content_type == 'file':
|
||||||
file_path = os.path.join(current_app.config['UPLOAD_FOLDER'], content_data)
|
file_path = os.path.join(app.config['UPLOAD_FOLDER'], content_data)
|
||||||
app.logger.info(f"Attempting to serve file: {file_path}")
|
|
||||||
if os.path.exists(file_path):
|
if os.path.exists(file_path):
|
||||||
if 'download' in request.path:
|
file_size = os.path.getsize(file_path)
|
||||||
return send_file(file_path, as_attachment=True)
|
file_extension = os.path.splitext(content_data)[1].lower()
|
||||||
else:
|
is_image = file_extension in ['.jpg', '.jpeg', '.png', '.gif']
|
||||||
return send_file(file_path)
|
return render_template('og_file.html',
|
||||||
else:
|
filename=content_data,
|
||||||
app.logger.error(f"File not found: {file_path}")
|
file_size=file_size,
|
||||||
return "File not found", 404
|
username=username,
|
||||||
|
created_at=created_at,
|
||||||
|
is_image=is_image,
|
||||||
|
file_url=url_for('redirect_vanity', vanity=vanity, _external=True))
|
||||||
elif content_type == 'pastebin':
|
elif content_type == 'pastebin':
|
||||||
return render_pastebin(content_data, created_at, user_id, username, vanity, is_private)
|
first_lines = '\n'.join(content_data.split('\n')[:5]) # Get first 5 lines
|
||||||
|
return render_template('og_pastebin.html',
|
||||||
|
vanity=vanity,
|
||||||
|
first_lines=first_lines,
|
||||||
|
username=username,
|
||||||
|
created_at=created_at)
|
||||||
|
|
||||||
app.logger.error(f"Content not found for vanity: {vanity}")
|
app.logger.error(f"Content not found for vanity: {vanity}")
|
||||||
return "Not found", 404
|
return "Not found", 404
|
||||||
@ -330,17 +337,6 @@ def raw_vanity(vanity, password=None):
|
|||||||
|
|
||||||
return content_data, 200, {'Content-Type': 'text/plain; charset=utf-8'}
|
return content_data, 200, {'Content-Type': 'text/plain; charset=utf-8'}
|
||||||
return 'Not Found', 404
|
return 'Not Found', 404
|
||||||
# Replace the LoginForm and RegistrationForm classes with simple classes
|
|
||||||
class LoginForm:
|
|
||||||
def __init__(self, username, password, remember):
|
|
||||||
self.username = username
|
|
||||||
self.password = password
|
|
||||||
self.remember = remember
|
|
||||||
|
|
||||||
class RegistrationForm:
|
|
||||||
def __init__(self, username, password):
|
|
||||||
self.username = username
|
|
||||||
self.password = password
|
|
||||||
|
|
||||||
@app.route('/login', methods=['GET', 'POST'])
|
@app.route('/login', methods=['GET', 'POST'])
|
||||||
def login():
|
def login():
|
||||||
@ -348,16 +344,15 @@ def login():
|
|||||||
username = request.form['username']
|
username = request.form['username']
|
||||||
password = request.form['password']
|
password = request.form['password']
|
||||||
remember = 'remember' in request.form
|
remember = 'remember' in request.form
|
||||||
form = LoginForm(username, password, remember)
|
|
||||||
db = get_db()
|
db = get_db()
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
cursor.execute("SELECT * FROM users WHERE username = ?", (form.username,))
|
cursor.execute("SELECT * FROM users WHERE username = ?", (username,))
|
||||||
user = cursor.fetchone()
|
user = cursor.fetchone()
|
||||||
if user and User.verify_password(user[2], form.password):
|
if user and User.verify_password(user[2], password):
|
||||||
user_obj = User(user[0], user[1], user[2], user[3])
|
user_obj = User(user[0], user[1], user[2], user[3])
|
||||||
login_user(user_obj, remember=form.remember)
|
login_user(user_obj, remember=remember)
|
||||||
return redirect(url_for('user_files', username=form.username))
|
return jsonify({'success': True, 'redirect': url_for('user_files', username=username)})
|
||||||
return "Invalid username or password"
|
return jsonify({'success': False, 'error': 'Invalid username or password'})
|
||||||
return render_template('login.html')
|
return render_template('login.html')
|
||||||
|
|
||||||
@app.route('/register', methods=['GET', 'POST'])
|
@app.route('/register', methods=['GET', 'POST'])
|
||||||
@ -365,23 +360,26 @@ def register():
|
|||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
username = request.form['username']
|
username = request.form['username']
|
||||||
password = request.form['password']
|
password = request.form['password']
|
||||||
api_key = User.generate_api_key() # Generate API key
|
|
||||||
|
if len(password) < 5 or not any(c.isupper() for c in password):
|
||||||
|
return jsonify({'success': False, 'error': 'Password does not meet requirements'})
|
||||||
|
|
||||||
|
api_key = User.generate_api_key()
|
||||||
db = get_db()
|
db = get_db()
|
||||||
cursor = db.cursor()
|
cursor = db.cursor()
|
||||||
cursor.execute("SELECT * FROM users WHERE username = ?", (username,))
|
cursor.execute("SELECT * FROM users WHERE username = ?", (username,))
|
||||||
if cursor.fetchone():
|
if cursor.fetchone():
|
||||||
return "Username already exists"
|
return jsonify({'success': False, 'error': 'Username already exists'})
|
||||||
hashed_password = User.hash_password(password)
|
hashed_password = User.hash_password(password)
|
||||||
cursor.execute("INSERT INTO users (username, password_hash, api_key) VALUES (?, ?, ?)",
|
cursor.execute("INSERT INTO users (username, password_hash, api_key) VALUES (?, ?, ?)",
|
||||||
(username, hashed_password, api_key))
|
(username, hashed_password, api_key))
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
# Create user directory
|
|
||||||
user_folder = os.path.join(app.config['UPLOAD_FOLDER'], username)
|
user_folder = os.path.join(app.config['UPLOAD_FOLDER'], username)
|
||||||
if not os.path.exists(user_folder):
|
if not os.path.exists(user_folder):
|
||||||
os.makedirs(user_folder)
|
os.makedirs(user_folder)
|
||||||
|
|
||||||
return redirect(url_for('login'))
|
return jsonify({'success': True, 'redirect': url_for('login')})
|
||||||
return render_template('register.html')
|
return render_template('register.html')
|
||||||
|
|
||||||
@app.route('/logout')
|
@app.route('/logout')
|
||||||
@ -819,7 +817,7 @@ def generate_sharex_config():
|
|||||||
base_url = request.url_root.replace('http://', 'https://', 1).rstrip('/')
|
base_url = request.url_root.replace('http://', 'https://', 1).rstrip('/')
|
||||||
config = {
|
config = {
|
||||||
"Version": "13.7.0",
|
"Version": "13.7.0",
|
||||||
"Name": "aCloud",
|
"Name": "sxbin",
|
||||||
"DestinationType": "ImageUploader, TextUploader, FileUploader, URLShortener",
|
"DestinationType": "ImageUploader, TextUploader, FileUploader, URLShortener",
|
||||||
"RequestMethod": "POST",
|
"RequestMethod": "POST",
|
||||||
"RequestURL": f"{base_url}/api/upload",
|
"RequestURL": f"{base_url}/api/upload",
|
||||||
@ -836,7 +834,7 @@ def generate_sharex_config():
|
|||||||
|
|
||||||
response = make_response(json.dumps(config, indent=2))
|
response = make_response(json.dumps(config, indent=2))
|
||||||
response.headers.set('Content-Type', 'application/json')
|
response.headers.set('Content-Type', 'application/json')
|
||||||
response.headers.set('Content-Disposition', 'attachment', filename='aCloud_ShareX.sxcu')
|
response.headers.set('Content-Disposition', 'attachment', filename='sxbin_ShareX.sxcu')
|
||||||
return response
|
return response
|
||||||
|
|
||||||
@app.route('/api/upload', methods=['POST'])
|
@app.route('/api/upload', methods=['POST'])
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>aCloud - File Sharing Service</title>
|
<title>sxbin - File Sharing Service</title>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
font-family: Arial, sans-serif;
|
font-family: Arial, sans-serif;
|
||||||
@ -110,6 +110,10 @@
|
|||||||
font-size: 1.2em;
|
font-size: 1.2em;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
}
|
}
|
||||||
.cursor {
|
.cursor {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@ -399,7 +403,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
const message1 = "Welcome to aCloud.";
|
const message1 = "Welcome to sxbin.gay";
|
||||||
const message2 = "\nA simple toolbox for file uploading,\nURL shortening and pastebin.";
|
const message2 = "\nA simple toolbox for file uploading,\nURL shortening and pastebin.";
|
||||||
const typewriterTextElement = document.getElementById('typewriter-text');
|
const typewriterTextElement = document.getElementById('typewriter-text');
|
||||||
const cursorElement = document.getElementById('cursor');
|
const cursorElement = document.getElementById('cursor');
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Login - aCloud</title>
|
<title>Login - sxbin</title>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
font-family: Arial, sans-serif;
|
font-family: Arial, sans-serif;
|
||||||
@ -97,37 +97,54 @@
|
|||||||
background-color: #2a2a2a;
|
background-color: #2a2a2a;
|
||||||
color: #f0f0f0;
|
color: #f0f0f0;
|
||||||
}
|
}
|
||||||
|
.error-message {
|
||||||
|
background-color: #ff6b6b;
|
||||||
|
color: white;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<a href="/" class="back-button">←</a>
|
<a href="/" class="back-button">←</a>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h2>Login</h2>
|
<h2>Login to sxbin</h2>
|
||||||
<form method="POST">
|
<div id="error-message" class="error-message"></div>
|
||||||
<div>
|
<form id="login-form" method="POST">
|
||||||
<label for="username">Username:</label>
|
<label for="username">Username:</label>
|
||||||
<input type="text" id="username" name="username" required>
|
<input type="text" id="username" name="username" required>
|
||||||
</div>
|
<label for="password">Password:</label>
|
||||||
<div>
|
<input type="password" id="password" name="password" required>
|
||||||
<label for="password">Password:</label>
|
<label>
|
||||||
<input type="password" id="password" name="password" required>
|
<input type="checkbox" name="remember"> Remember me
|
||||||
</div>
|
</label>
|
||||||
<div class="remember-me">
|
<input type="submit" value="Login">
|
||||||
<input type="checkbox" id="remember" name="remember">
|
|
||||||
<label for="remember">Remember me</label>
|
|
||||||
</div>
|
|
||||||
<button type="submit">Login</button>
|
|
||||||
</form>
|
</form>
|
||||||
<p>Don't have an account? <a href="{{ url_for('register') }}">Register here</a></p>
|
<p>Don't have an account? <a href="{{ url_for('register') }}">Register</a></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<footer class="footer">
|
|
||||||
<p>
|
<script>
|
||||||
Source code: <a href="https://git.spitkov.hu/cgcristi/aCloud" target="_blank">Spitkov's Git</a> |
|
document.getElementById('login-form').addEventListener('submit', function(e) {
|
||||||
<a href="https://office.bence.lol/form/#/2/form/view/z5Cf3CL6tZtPjzKsbcEPync6JE3iyMl22h6thUQg1a4/" target="_blank">Suggestions & Bugs</a> |
|
e.preventDefault();
|
||||||
<a href="https://office.bence.lol/kanban/#/2/kanban/view/hx6RTcpN0pR7hc1HHkMzG4awMoMdHjR2zbHjG7Xh+wU/embed/" target="_blank">Todo List</a>
|
|
||||||
</p>
|
fetch('/login', {
|
||||||
</footer>
|
method: 'POST',
|
||||||
|
body: new FormData(this),
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
window.location.href = data.redirect;
|
||||||
|
} else {
|
||||||
|
document.getElementById('error-message').textContent = data.error;
|
||||||
|
document.getElementById('error-message').style.display = 'block';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
26
templates/og_file.html
Normal file
26
templates/og_file.html
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>{{ filename }} - sxbin</title>
|
||||||
|
<meta property="og:title" content="{{ filename }}">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:url" content="{{ request.url }}">
|
||||||
|
<meta property="og:description" content="File size: {{ file_size|filesizeformat }} | Uploaded by: {{ username }} | Date: {{ created_at.strftime('%Y-%m-%d %H:%M:%S') }}">
|
||||||
|
{% if is_image %}
|
||||||
|
<meta property="og:image" content="{{ file_url }}">
|
||||||
|
{% endif %}
|
||||||
|
<meta property="og:site_name" content="sxbin">
|
||||||
|
<meta property="theme-color" content="#4CAF50">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>{{ filename }}</h1>
|
||||||
|
<p>File size: {{ file_size|filesizeformat }}</p>
|
||||||
|
<p>Uploaded by: {{ username }}</p>
|
||||||
|
<p>Date: {{ created_at.strftime('%Y-%m-%d %H:%M:%S') }}</p>
|
||||||
|
{% if is_image %}
|
||||||
|
<img src="{{ file_url }}" alt="{{ filename }}">
|
||||||
|
{% endif %}
|
||||||
|
</body>
|
||||||
|
</html>
|
20
templates/og_pastebin.html
Normal file
20
templates/og_pastebin.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Pastebin {{ vanity }} - sxbin</title>
|
||||||
|
<meta property="og:title" content="Pastebin {{ vanity }}">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:url" content="{{ request.url }}">
|
||||||
|
<meta property="og:description" content="{{ first_lines|truncate(200) }}">
|
||||||
|
<meta property="og:site_name" content="sxbin">
|
||||||
|
<meta property="theme-color" content="#4CAF50">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Pastebin {{ vanity }}</h1>
|
||||||
|
<pre>{{ first_lines }}</pre>
|
||||||
|
<p>Created by: {{ username }}</p>
|
||||||
|
<p>Date: {{ created_at.strftime('%Y-%m-%d %H:%M:%S') }}</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
23
templates/og_shorturl.html
Normal file
23
templates/og_shorturl.html
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Shortened URL - sxbin</title>
|
||||||
|
<meta property="og:title" content="Shortened URL">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:url" content="{{ request.url }}">
|
||||||
|
<meta property="og:description" content="Shortened link created by {{ username }} on {{ created_at.strftime('%Y-%m-%d %H:%M:%S') }}">
|
||||||
|
<meta property="og:site_name" content="sxbin">
|
||||||
|
<meta property="theme-color" content="#4CAF50">
|
||||||
|
<meta http-equiv="refresh" content="0;url={{ long_url }}">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Shortened URL</h1>
|
||||||
|
<p>Redirecting to: {{ long_url }}</p>
|
||||||
|
<p>Created by: {{ username }}</p>
|
||||||
|
<p>Date: {{ created_at.strftime('%Y-%m-
|
||||||
|
|
||||||
|
%d %H:%M:%S') }}</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Register - aCloud</title>
|
<title>Register - sxbin</title>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
font-family: Arial, sans-serif;
|
font-family: Arial, sans-serif;
|
||||||
@ -89,33 +89,83 @@
|
|||||||
background-color: #2a2a2a;
|
background-color: #2a2a2a;
|
||||||
color: #f0f0f0;
|
color: #f0f0f0;
|
||||||
}
|
}
|
||||||
|
.error-message {
|
||||||
|
background-color: #ff6b6b;
|
||||||
|
color: white;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.password-requirement {
|
||||||
|
font-size: 0.9em;
|
||||||
|
margin-top: 5px;
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.requirement-not-met {
|
||||||
|
color: #ff6b6b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.requirement-met {
|
||||||
|
color: #4CAF50;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<a href="/" class="back-button">←</a>
|
<a href="/" class="back-button">←</a>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<h2>Register</h2>
|
<h2>Register for sxbin</h2>
|
||||||
<form method="POST">
|
<div id="error-message" class="error-message"></div>
|
||||||
<div>
|
<form id="register-form" method="POST">
|
||||||
<label for="username">Username:</label>
|
<label for="username">Username:</label>
|
||||||
<input type="text" id="username" name="username" required>
|
<input type="text" id="username" name="username" required>
|
||||||
</div>
|
<label for="password">Password:</label>
|
||||||
<div>
|
<input type="password" id="password" name="password" required>
|
||||||
<label for="password">Password:</label>
|
<div id="password-length" class="password-requirement requirement-not-met">At least 5 characters</div>
|
||||||
<input type="password" id="password" name="password" required>
|
<div id="password-uppercase" class="password-requirement requirement-not-met">At least one uppercase letter</div>
|
||||||
</div>
|
<input type="submit" value="Register" id="submit-button" disabled>
|
||||||
<button type="submit">Register</button>
|
|
||||||
</form>
|
</form>
|
||||||
<p>Already have an account? <a href="{{ url_for('login') }}">Login here</a></p>
|
<p>Already have an account? <a href="{{ url_for('login') }}">Login</a></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<footer class="footer">
|
|
||||||
<p>
|
<script>
|
||||||
Source code: <a href="https://git.spitkov.hu/cgcristi/aCloud" target="_blank">Spitkov's Git</a> |
|
const passwordInput = document.getElementById('password');
|
||||||
<a href="https://office.bence.lol/form/#/2/form/view/z5Cf3CL6tZtPjzKsbcEPync6JE3iyMl22h6thUQg1a4/" target="_blank">Suggestions & Bugs</a> |
|
const lengthRequirement = document.getElementById('password-length');
|
||||||
<a href="https://office.bence.lol/kanban/#/2/kanban/view/hx6RTcpN0pR7hc1HHkMzG4awMoMdHjR2zbHjG7Xh+wU/embed/" target="_blank">Todo List</a>
|
const uppercaseRequirement = document.getElementById('password-uppercase');
|
||||||
</p>
|
const submitButton = document.getElementById('submit-button');
|
||||||
</footer>
|
|
||||||
|
passwordInput.addEventListener('input', function() {
|
||||||
|
const password = this.value;
|
||||||
|
const meetsLengthRequirement = password.length >= 5;
|
||||||
|
const meetsUppercaseRequirement = /[A-Z]/.test(password);
|
||||||
|
|
||||||
|
lengthRequirement.className = meetsLengthRequirement ? 'password-requirement requirement-met' : 'password-requirement requirement-not-met';
|
||||||
|
uppercaseRequirement.className = meetsUppercaseRequirement ? 'password-requirement requirement-met' : 'password-requirement requirement-not-met';
|
||||||
|
|
||||||
|
submitButton.disabled = !(meetsLengthRequirement && meetsUppercaseRequirement);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('register-form').addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
fetch('/register', {
|
||||||
|
method: 'POST',
|
||||||
|
body: new FormData(this),
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.success) {
|
||||||
|
window.location.href = data.redirect;
|
||||||
|
} else {
|
||||||
|
document.getElementById('error-message').textContent = data.error;
|
||||||
|
document.getElementById('error-message').style.display = 'block';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
Loading…
Reference in New Issue
Block a user