and i think that's it, we now support user accounts (lite)git commit -m 'and i think that\'s it, we now support user accounts litegit status sweet.'! sweet.

This commit is contained in:
Andrej Karpathy 2021-11-26 16:38:36 -08:00
parent 54157c6e9c
commit c5b5c7833c
5 changed files with 112 additions and 6 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@
__pycache__ __pycache__
data data
*.ipynb *.ipynb
secret_key.txt

View File

@ -7,8 +7,8 @@ ideas:
- special single-image search just for paper similarity - special single-image search just for paper similarity
""" """
import os
import time import time
import pickle
from random import shuffle from random import shuffle
import numpy as np import numpy as np
@ -17,6 +17,7 @@ from sklearn import svm
from flask import Flask, request, redirect, url_for from flask import Flask, request, redirect, url_for
from flask import render_template from flask import render_template
from flask import g # global session-level object from flask import g # global session-level object
from flask import session
from aslite.db import get_papers_db, get_metas_db, get_tags_db from aslite.db import get_papers_db, get_metas_db, get_tags_db
from aslite.db import load_features from aslite.db import load_features
@ -24,9 +25,20 @@ from aslite.db import load_features
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# inits and globals # inits and globals
app = Flask(__name__)
RET_NUM = 100 # number of papers to return per page RET_NUM = 100 # number of papers to return per page
app = Flask(__name__)
# set the secret key so we can cryptographically sign cookies and maintain sessions
if os.path.isfile('secret_key.txt'):
# example of generating a good key on your system is:
# import secrets; secrets.token_urlsafe(16)
sk = open('secret_key.txt').read().strip()
else:
print("WARNING: no secret key found, using default devkey")
sk = 'devkey'
app.secret_key = sk
# ----------------------------------------------------------------------------- # -----------------------------------------------------------------------------
# globals that manage the (lazy) loading of various state for a request # globals that manage the (lazy) loading of various state for a request
@ -51,8 +63,7 @@ def get_metas():
@app.before_request @app.before_request
def before_request(): def before_request():
g.user = 'root' # current default user, as we have no accounts db at this time just yet g.user = session.get('user', None)
#g.user = None # if noone is logged in, will be the default state shortly
@app.teardown_request @app.teardown_request
def close_connection(error=None): def close_connection(error=None):
@ -355,3 +366,22 @@ def delete_tag(tag=None):
print("deleted tag %s for user %s" % (tag, g.user)) print("deleted tag %s for user %s" % (tag, g.user))
return "ok: " + str(d) # return back the user library for debugging atm return "ok: " + str(d) # return back the user library for debugging atm
# -----------------------------------------------------------------------------
# endpoints to log in and out
@app.route('/login', methods=['POST'])
def login():
# the user is logged out but wants to log in, ok
if g.user is None and request.form['username']:
username = request.form['username']
if len(username) > 0: # one more paranoid check
session['user'] = username
return redirect(url_for('profile'))
@app.route('/logout')
def logout():
session.pop('user', None)
return redirect(url_for('profile'))

View File

@ -181,3 +181,46 @@ body {
right: 10px; right: 10px;
top: 10px; top: 10px;
} }
#profile-warning {
margin: 10px;
padding: 10px;
font-size: 16px;
background-color: #fdd;
border-radius: 5px;
}
#profile-warning p {
margin: 0;
padding: 0;
}
#profile-login-form {
width: 400px;
margin: 30px auto;
font-size: 18px;
}
#profile-login-form .form-control {
display: block;
width: 100%;
box-sizing: border-box;
margin: 5px 0 10px 0;
padding: 5px;
height: 34px;
font-size: 16px;
line-height: 1.42857143;
color: #555;
border: 1px solid #ccc;
border-radius: 4px;
}
#profile-login-form .btn {
display: block;
width: 100%;
padding: 5px;
margin: 0;
height: 34px;
font-size: 14px;
line-height: 1.42857143;
color: #fff;
background-color: #337ab7;
border: 1px solid #2e6da4;
border-radius: 4px;
cursor: pointer;
}

View File

@ -65,7 +65,7 @@ var gvars = {{ gvars | tojson }};
</div> </div>
</div> </div>
{% if user %} {% if user and tags %}
<div id="tagwrap"> <div id="tagwrap">
</div> </div>
{% endif %} {% endif %}

View File

@ -5,7 +5,39 @@
{% block content %} {% block content %}
<div id="wrap"> <div id="wrap">
This is where the user gets to log in, or see information about their account if logged in.
{% if user %}
<div>
<div>Logged in user: {{ user }}</div>
<div>
<a href="{{ url_for('logout') }}">Log out</a>
</div>
</div>
{% else %}
<div>
<div id="profile-warning">
<p>
Okay, arxiv-sanity-lite uses a super lite version of
"user accounts" where there are no passwords. Basically, you can "log in"
with any arbitrary username. If you want to share your library with a
friend, you can just tell them the username. And if you'd like to keep your
account private, just make your username be something unique
and write it down somewhere safe.
</p>
<b>TLDR: there are no passwords!</b>
</div>
<form id="profile-login-form" action="/login" method="POST">
<div class="form-group">
<label>Username:</label>
<input class="form-control" type="text" name="username">
</div>
<button type="submit" class="btn btn-primary">Log in</button>
</form>
</div>
{% endif %}
</div> </div>
{% endblock %} {% endblock %}