martynka commited on
Commit
a0be3b9
·
verified ·
1 Parent(s): ecfbb6a

Update Dockerfile

Browse files
Files changed (1) hide show
  1. Dockerfile +59 -76
Dockerfile CHANGED
@@ -156,111 +156,94 @@ document.addEventListener('DOMContentLoaded', () => {
156
  });
157
  EOF
158
 
159
- # ===== Fixed Combined Server =====
160
- COPY <<"EOF" /app/combined_server.py
161
- from flask import Flask, request, jsonify, render_template, send_from_directory
162
- from werkzeug.middleware.proxy_fix import ProxyFix
163
- from werkzeug.security import generate_password_hash
164
- import os
165
  import sqlite3
166
- from pathlib import Path
167
  import subprocess
168
- import requests
169
- from waitress import serve
170
  import threading
171
- import time
 
172
 
173
- app = Flask(__name__,
174
- static_url_path='/admin/static',
175
- static_folder='/app/admin/static',
176
- template_folder='/app/admin/templates')
177
- app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1)
178
- app.secret_key = os.getenv("FLASK_SECRET")
179
 
180
  # Database setup
181
- DB_PATH = '/app/data/admin.db'
182
-
183
  def get_db():
184
- Path(DB_PATH).parent.mkdir(exist_ok=True)
185
- db = sqlite3.connect(DB_PATH)
186
- db.execute('''CREATE TABLE IF NOT EXISTS users
187
- (username TEXT PRIMARY KEY, password TEXT, role TEXT)''')
188
- return db
 
 
 
 
189
 
190
- # ===== Admin Routes =====
191
- @app.route('/admin')
192
  @app.route('/sudo')
193
- def admin_home():
194
  return render_template('login.html')
195
 
196
- @app.route('/admin/login', methods=['POST'])
197
  @app.route('/sudo/login', methods=['POST'])
198
  def login():
199
  if request.json.get('sudo_secret') == os.getenv("SUDO_SECRET"):
200
  return jsonify({
201
- "status": "success",
202
- "token": os.getenv("SUDO_SECRET"),
203
- "redirect": "/admin/dashboard"
204
  })
205
- return jsonify({"error": "Invalid secret"}), 403
206
 
207
- @app.route('/admin/dashboard')
208
  @app.route('/sudo/dashboard')
209
  def dashboard():
210
  return render_template('dashboard.html')
211
 
212
- # [Keep other admin routes...]
213
-
214
- # Serve admin static files
215
- @app.route('/admin/static/<path:filename>')
216
- def admin_static(filename):
217
- return send_from_directory('/app/admin/static', filename)
218
-
219
- # ===== LibreChat Proxy =====
220
- def is_librechat_ready():
221
  try:
222
- return requests.get('http://localhost:3080/api', timeout=1).status_code < 500
223
- except:
224
- return False
 
 
 
 
 
225
 
226
- @app.route('/', defaults={'path': ''})
227
- @app.route('/<path:path>')
228
- def proxy(path):
229
- # Don't proxy admin routes
230
- if path.startswith(('admin/', 'sudo/', 'admin', 'sudo')):
231
- return "Route not found", 404
232
-
233
- # Wait for backend
234
- if not is_librechat_ready():
235
- return "LibreChat backend starting...", 503
236
 
237
- # Forward request
238
- resp = requests.request(
239
- method=request.method,
240
- url=f"http://localhost:3080/{path}",
241
- headers={k: v for k, v in request.headers if k.lower() != 'host'},
242
- data=request.get_data(),
243
- cookies=request.cookies,
244
- allow_redirects=False
245
- )
246
 
247
- # Build response
248
- response = app.make_response((resp.content, resp.status_code))
249
- for k, v in resp.headers.items():
250
- if k.lower() not in ['content-length', 'transfer-encoding']:
251
- response.headers[k] = v
252
- return response
253
 
 
254
  def start_librechat():
255
- subprocess.Popen(["npm", "run", "backend"], cwd="/app")
 
 
256
 
 
257
  if __name__ == "__main__":
258
- # Start LibreChat
259
- threading.Thread(target=start_librechat, daemon=True).start()
260
-
261
- # Start server
262
- print("Starting combined server on port 7860")
263
- serve(app, host='0.0.0.0', port=7860, threads=4)
264
  EOF
265
 
266
  # Startup script
 
156
  });
157
  EOF
158
 
159
+ # 3. Create the Python server
160
+ COPY <<"EOF" /app/server.py
161
+ from flask import Flask, request, jsonify, render_template
162
+ from waitress import serve
 
 
163
  import sqlite3
 
164
  import subprocess
 
 
165
  import threading
166
+ import os
167
+ from werkzeug.security import generate_password_hash
168
 
169
+ app = Flask(__name__, template_folder='/app/admin/templates')
170
+ app.secret_key = os.getenv("FLASK_SECRET", "secret-key-123")
 
 
 
 
171
 
172
  # Database setup
 
 
173
  def get_db():
174
+ conn = sqlite3.connect('/app/data/users.db')
175
+ conn.execute('''
176
+ CREATE TABLE IF NOT EXISTS users (
177
+ username TEXT PRIMARY KEY,
178
+ password TEXT,
179
+ role TEXT DEFAULT 'user'
180
+ )
181
+ ''')
182
+ return conn
183
 
184
+ # Admin routes
 
185
  @app.route('/sudo')
186
+ def admin_login():
187
  return render_template('login.html')
188
 
 
189
  @app.route('/sudo/login', methods=['POST'])
190
  def login():
191
  if request.json.get('sudo_secret') == os.getenv("SUDO_SECRET"):
192
  return jsonify({
193
+ "status": "success",
194
+ "token": os.getenv("SUDO_SECRET")
 
195
  })
196
+ return jsonify({"error": "Invalid password"}), 403
197
 
 
198
  @app.route('/sudo/dashboard')
199
  def dashboard():
200
  return render_template('dashboard.html')
201
 
202
+ @app.route('/sudo/add_user', methods=['POST'])
203
+ def add_user():
204
+ if request.headers.get('X-Sudo-Secret') != os.getenv("SUDO_SECRET"):
205
+ return jsonify({"error": "Unauthorized"}), 403
206
+
207
+ db = get_db()
 
 
 
208
  try:
209
+ db.execute(
210
+ "INSERT INTO users (username, password) VALUES (?, ?)",
211
+ [request.json["username"], generate_password_hash(request.json["password"])]
212
+ )
213
+ db.commit()
214
+ return jsonify({"status": "User added"})
215
+ except sqlite3.IntegrityError:
216
+ return jsonify({"error": "User exists"}), 400
217
 
218
+ @app.route('/sudo/list_users', methods=['GET'])
219
+ def list_users():
220
+ if request.headers.get('X-Sudo-Secret') != os.getenv("SUDO_SECRET"):
221
+ return jsonify({"error": "Unauthorized"}), 403
 
 
 
 
 
 
222
 
223
+ db = get_db()
224
+ users = db.execute("SELECT username FROM users").fetchall()
225
+ return jsonify([{"username": u[0]} for u in users])
226
+
227
+ @app.route('/sudo/remove_user', methods=['POST'])
228
+ def remove_user():
229
+ if request.headers.get('X-Sudo-Secret') != os.getenv("SUDO_SECRET"):
230
+ return jsonify({"error": "Unauthorized"}), 403
 
231
 
232
+ db = get_db()
233
+ db.execute("DELETE FROM users WHERE username = ?", [request.json["username"]])
234
+ db.commit()
235
+ return jsonify({"status": "User deleted"})
 
 
236
 
237
+ # Start LibreChat in background
238
  def start_librechat():
239
+ subprocess.run(["npm", "run", "backend"], cwd="/app")
240
+
241
+ threading.Thread(target=start_librechat, daemon=True).start()
242
 
243
+ # Start server
244
  if __name__ == "__main__":
245
+ print("Admin panel: http://localhost:7860/sudo")
246
+ serve(app, host="0.0.0.0", port=7860)
 
 
 
 
247
  EOF
248
 
249
  # Startup script