mirror of
https://github.com/zoffline/zwift-offline.git
synced 2026-01-15 14:23:49 -08:00
Nits, niceties, randomized secret
This commit is contained in:
@@ -24,6 +24,12 @@
|
||||
<input type="password" id="password" name="password" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<label>Confirm Password</label>
|
||||
<input type="password" id="confirm_password" name="confirm_password" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<label>First name</label>
|
||||
|
||||
@@ -19,8 +19,6 @@
|
||||
<a href="{{ url_for('logout', username=username) }}" class="btn btn-outline-secondary">Logout</a>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<a href="{{ url_for('upload', username=username) }}" class="btn btn-outline-success">Upload</a>
|
||||
{% endif %}
|
||||
<form method="POST" action="/start-zwift">
|
||||
<div class="row">
|
||||
|
||||
@@ -298,11 +298,14 @@ class UDPHandler(socketserver.BaseRequestHandler):
|
||||
data = self.request[0]
|
||||
socket = self.request[1]
|
||||
recv = udp_node_msgs_pb2.ClientToServer()
|
||||
|
||||
|
||||
try:
|
||||
recv.ParseFromString(data[:-4])
|
||||
except:
|
||||
recv.ParseFromString(data[3:-4])
|
||||
try:
|
||||
recv.ParseFromString(data[3:-4])
|
||||
except:
|
||||
return
|
||||
|
||||
client_address = self.client_address
|
||||
player_id = recv.player_id
|
||||
|
||||
@@ -76,6 +76,7 @@ DATABASE_CUR_VER = 2
|
||||
# For auth server
|
||||
AUTOLAUNCH_FILE = "%s/auto_launch.txt" % STORAGE_DIR
|
||||
SERVER_IP_FILE = "%s/server-ip.txt" % STORAGE_DIR
|
||||
SECRET_KEY_FILE = "%s/secret-key.txt" % STORAGE_DIR
|
||||
MULTIPLAYER = False
|
||||
if os.path.exists("%s/multiplayer.txt" % STORAGE_DIR):
|
||||
MULTIPLAYER = True
|
||||
@@ -87,7 +88,11 @@ AUTH_PATH = "%s/auth.db" % STORAGE_DIR
|
||||
app = Flask(__name__, static_folder='%s/cdn/gameassets' % SCRIPT_DIR, static_url_path='/gameassets', template_folder='%s/cdn/static/web/launcher' % SCRIPT_DIR)
|
||||
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///{db}'.format(db=AUTH_PATH)
|
||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||
app.config['SECRET_KEY'] = 'zoffline'
|
||||
if not os.path.exists(SECRET_KEY_FILE):
|
||||
with open(SECRET_KEY_FILE, 'wb') as f:
|
||||
f.write(os.urandom(16))
|
||||
with open(SECRET_KEY_FILE, 'rb') as f:
|
||||
app.config['SECRET_KEY'] = f.read()
|
||||
app.config['MAX_CONTENT_LENGTH'] = 1024 * 1024
|
||||
|
||||
db = SQLAlchemy(app)
|
||||
@@ -240,12 +245,16 @@ def signup():
|
||||
if request.method == "POST":
|
||||
username = request.form['username']
|
||||
password = request.form['password']
|
||||
confirm_password = request.form['confirm_password']
|
||||
first_name = request.form['first_name']
|
||||
last_name = request.form['last_name']
|
||||
|
||||
if not (username and password and first_name and last_name):
|
||||
if not (username and password and confirm_password and first_name and last_name):
|
||||
flash("All fields are required.")
|
||||
return redirect(url_for('signup'))
|
||||
if password != confirm_password:
|
||||
flash("Passwords did not match.")
|
||||
return redirect(url_for('signup'))
|
||||
|
||||
hashed_pwd = generate_password_hash(password, 'sha256')
|
||||
|
||||
@@ -301,7 +310,7 @@ def upload(username):
|
||||
os.makedirs(profile_dir)
|
||||
except IOError as e:
|
||||
logger.error("failed to create profile dir (%s): %s", profile_dir, str(e))
|
||||
sys.exit(1)
|
||||
return '', 500
|
||||
|
||||
if request.method == 'POST':
|
||||
uploaded_file = request.files['file']
|
||||
@@ -327,7 +336,7 @@ def upload(username):
|
||||
stat = os.stat(token_file)
|
||||
token = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(stat.st_mtime))
|
||||
|
||||
return render_template("upload.html", username=username, profile=profile, name=name, token=token)
|
||||
return render_template("upload.html", username=current_user.username, profile=profile, name=name, token=token)
|
||||
|
||||
|
||||
@app.route("/logout/<username>")
|
||||
@@ -514,7 +523,7 @@ def api_profiles_me():
|
||||
os.makedirs(profile_dir)
|
||||
except IOError as e:
|
||||
logger.error("failed to create profile dir (%s): %s", profile_dir, str(e))
|
||||
sys.exit(1)
|
||||
return '', 500
|
||||
profile = profile_pb2.Profile()
|
||||
profile_file = '%s/profile.bin' % profile_dir
|
||||
if not os.path.isfile(profile_file):
|
||||
@@ -527,6 +536,17 @@ def api_profiles_me():
|
||||
with open(profile_file, 'rb') as fd:
|
||||
profile.ParseFromString(fd.read())
|
||||
if MULTIPLAYER:
|
||||
# For newly added existing profiles, User's player id likely differs from profile's player id.
|
||||
# If there's existing data in db for this profile, update it for the newly assigned player id.
|
||||
# XXX: Users can maliciously abuse this by intentionally uploading a profile with another user's current player id.
|
||||
# However, without it, anyone "upgrading" to multiplayer mode will lose their existing data.
|
||||
# TODO: need a warning in README that switching to multiplayer mode and back to single player will lose your existing data.
|
||||
if profile.id != profile_id:
|
||||
cur = g.db.cursor()
|
||||
cur.execute('UPDATE activity SET player_id = ? WHERE player_id = ?', (str(profile_id), str(profile.id)))
|
||||
cur.execute('UPDATE goal SET player_id = ? WHERE player_id = ?', (str(profile_id), str(profile.id)))
|
||||
cur.execute('UPDATE segment_result SET player_id = ? WHERE player_id = ?', (str(profile_id), str(profile.id)))
|
||||
g.db.commit()
|
||||
profile.id = profile_id
|
||||
elif current_user.player_id != profile.id:
|
||||
# Update AnonUser's player_id to match
|
||||
@@ -1328,28 +1348,6 @@ def static_web_launcher(filename):
|
||||
return render_template(filename)
|
||||
|
||||
|
||||
def check_columns():
|
||||
time.sleep(3)
|
||||
result = db.engine.execute(sqlalchemy.text("PRAGMA table_info(user)"))
|
||||
should_have_columns = User.metadata.tables['user'].columns
|
||||
current_columns = list()
|
||||
for row in result:
|
||||
current_columns.append(row[1])
|
||||
for column in should_have_columns:
|
||||
if not column.name in current_columns:
|
||||
nulltext = None
|
||||
if column.nullable:
|
||||
nulltext = "NULL"
|
||||
else:
|
||||
nulltext = "NOT NULL"
|
||||
defaulttext = None
|
||||
if column.default == None:
|
||||
defaulttext = ""
|
||||
else:
|
||||
defaulttext = " DEFAULT %s" % column.default.arg
|
||||
db.engine.execute(sqlalchemy.text("ALTER TABLE user ADD %s %s %s%s;" % (column.name, str(column.type), nulltext, defaulttext)))
|
||||
|
||||
|
||||
def run_standalone(passedOnline, passedGhostsEnabled, passedSaveGhost, passedPlayerUpdateQueue):
|
||||
global online
|
||||
global ghostsEnabled
|
||||
@@ -1363,11 +1361,11 @@ def run_standalone(passedOnline, passedGhostsEnabled, passedSaveGhost, passedPla
|
||||
login_manager = LoginManager()
|
||||
login_manager.login_view = 'login'
|
||||
login_manager.session_protection = None
|
||||
db.create_all(app=app)
|
||||
db.session.commit()
|
||||
if not MULTIPLAYER:
|
||||
login_manager.anonymous_user = AnonUser
|
||||
login_manager.init_app(app)
|
||||
db.create_all(app=app)
|
||||
db.session.commit()
|
||||
|
||||
@login_manager.user_loader
|
||||
def load_user(uid):
|
||||
|
||||
Reference in New Issue
Block a user