Compare commits

...

4 Commits

Author SHA1 Message Date
Derek d8a9565dc3
Misc improvements
1. Customise login_required and needs_refresh messages
2. Add titles (hover text) to buttons
3. Fade out flashed messages (in case they overflow the screen)
2018-09-08 12:51:04 -07:00
Derek 8add5cefda
Fixed bug where referals didnt carry user args over 2018-09-08 12:48:50 -07:00
Derek 58bd4895ce
Implemented referal creation flow 2018-09-08 12:48:10 -07:00
Derek e4b0f4cff8
Added new user permissions into db
can_refer: Can create referal codes
can_upload: Can upload new files
can_manage: Can perform administrative duties

All false by default except for user 'admin'
2018-09-08 10:55:46 -07:00
8 changed files with 171 additions and 18 deletions

View File

@ -0,0 +1,43 @@
"""empty message
Revision ID: 49984f04bc27
Revises: ea5307f715d1
Create Date: 2018-09-08 10:28:27.031642
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '49984f04bc27'
down_revision = 'ea5307f715d1'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('user', sa.Column('can_manage', sa.Boolean(), nullable=False, server_default=sa.false()))
op.add_column('user', sa.Column('can_refer', sa.Boolean(), nullable=False, server_default=sa.false()))
op.add_column('user', sa.Column('can_upload', sa.Boolean(), nullable=False, server_default=sa.false()))
user = sa.sql.table('user',
sa.sql.column('username', sa.String),
sa.sql.column('can_refer', sa.Boolean()),
sa.sql.column('can_upload', sa.Boolean()),
sa.sql.column('can_manage', sa.Boolean())
)
op.execute(
user.update().\
where(user.c.username==op.inline_literal('admin')).\
values({'can_refer':op.inline_literal(True), 'can_upload':op.inline_literal(True), 'can_manage':op.inline_literal(True)})
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('user', 'can_upload')
op.drop_column('user', 'can_refer')
op.drop_column('user', 'can_manage')
# ### end Alembic commands ###

View File

@ -11,13 +11,19 @@ class User(db.Model, UserMixin):
password = db.Column(db.String(64), nullable=False)
active = db.Column(db.Boolean(), nullable=False, index=True)
can_refer = db.Column(db.Boolean(), nullable=False)
can_upload = db.Column(db.Boolean(), nullable=False)
can_manage = db.Column(db.Boolean(), nullable=False)
referals = db.relationship('Referal', backref='user', lazy=True)
def __init__(self, username, password, active=True):
def __init__(self, username, password, active=True, can_refer=False, can_upload=False, can_manage=False):
self.username = username
self.set_password(password)
self.active = active
self.can_refer = can_refer
self.can_upload = can_upload
self.can_manage = can_manage
def __repr__(self):
return "<User {username} : active = {is_active}>".format(username=self.username, is_active=self.active)
@ -47,7 +53,7 @@ class Referal(db.Model):
self.user_id = user.id
self.key = secrets.token_urlsafe()
self.message = message
self.args = kwargs
self.kwargs = kwargs
def __repr__(self):
return "<Referal {id} : user = {user}>".format(id=self.id, user=self.user.username)

View File

@ -1,7 +1,7 @@
from flask import Flask, render_template, flash, send_from_directory, redirect, request, session, url_for
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager, current_user, login_user, logout_user, login_required
from flask_login import LoginManager, current_user, login_user, logout_user, login_required, fresh_login_required
from flask_limiter import Limiter
import flask_limiter.util
from operator import itemgetter
@ -20,6 +20,9 @@ migrate = Migrate(app, db)
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = "login"
login_manager.login_message = "slap them creds in to continue"
login_manager.needs_refresh_message = "no cookies for you - log in properly to continue"
login_manager.needs_refresh_message_category = 'info'
@login_manager.user_loader
def load_user(id):
@ -82,7 +85,8 @@ def signup():
else:
username = request.form['username']
password = request.form['password']
new_user = User(username, password)
referal_kwargs = referal.kwargs or {}
new_user = User(username, password, **referal_kwargs)
db.session.add(new_user)
db.session.delete(referal)
@ -102,16 +106,33 @@ def logout():
flash("bye binch", 'info')
return redirect(url_for('login'))
#FIXME: make this functionality avalible in a settings/admin view
@app.route('/newreferal')
@login_required
@limiter.limit("50/hour;2/second", key_func=lambda : current_user)
def newreferal():
referal = Referal(current_user)
db.session.add(referal)
db.session.commit()
@app.route('/refer', methods=['GET', 'POST'])
@fresh_login_required
@limiter.limit("50/hour;2/second", key_func=lambda : current_user, exempt_when=lambda : request.method == 'GET')
def refer():
if not current_user.can_refer:
return login_manager.unauthorized()
return referal.key
if request.method == 'GET':
return render_template('new_referal.html')
else:
can_refer = request.form.get('refer', 'off') == 'on'
can_upload = request.form.get('upload', 'off') == 'on'
can_manage = request.form.get('manage', 'off') == 'on'
message = request.form.get('message', None)
referal = Referal(current_user, message=message, can_refer=can_refer, can_upload=can_upload, can_manage=can_manage)
db.session.add(referal)
db.session.commit()
return redirect(url_for('show_referal', key=referal.key))
@app.route('/refer/show', methods=['GET'])
@login_required
def show_referal():
if not current_user.can_refer:
return login_manager.unauthorized()
return render_template('show_referal.html', key=request.args.get('key'))
@app.route('/browse/')
@app.route('/browse/<path:path>')

View File

@ -17,7 +17,7 @@ def main(serve_dir, secret=None, connection=None):
from notpiracyiswear import app, db, migrate
db.create_all()
admin = User('admin', app.config['SECRET_KEY'])
admin = User('admin', app.config['SECRET_KEY'], can_refer=True, can_upload=True)
db.session.add(admin)
db.session.commit()

View File

@ -86,6 +86,30 @@ button:active {
margin-bottom: 8px;
}
#referal_form {
display: flex;
flex-direction: column;
}
#referal_form > div {
display: flex;
flex-direction: row;
align-items: center;
}
#custom_message_text {
margin: 12px 0px;
}
#referal_form > button {
margin-top: 32px;
padding: 12px 24px;
}
#link_copy {
margin-top: 12px;
color: var(--secondary-foreground-color);
}
@keyframes fade { from { opacity: 1; } to { opacity: 0; } }
@keyframes slide { from { bottom: 0px; } to { bottom: -100%; } }
@ -94,10 +118,10 @@ button:active {
position: fixed;
bottom: 0px;
width: 100%;
animation: slide cubic-bezier(0.4, 0, 0.2, 1) 1;
animation: slide cubic-bezier(0.4, 0, 0.2, 1) 1, fade 1;
animation-fill-mode: forwards;
animation-delay: 4s;
animation-duration: 1s;
animation-delay: 4s, 4.5s;
animation-duration: 1s, 0.5s;
pointer-events: none;
}

View File

@ -0,0 +1,30 @@
{% extends 'skel.html' %}
{% block body %}
<div id="mainwrapper">
<div id="contentarea">
<p id="infohead">
Sharing is <span style='text-decoration: line-through;'>communism</span> caring
</p>
<p id="infodisc">
Referal links can be used only once to register a new user on this site, giving access to all it's content.
Give out with caution.
</p>
<form id="referal_form" action="" method="post" style="padding-top: 32px;">
<div id="refer_container">
<input id="refer_permission_checkbox" name="refer" type="checkbox"></input>
<p>Allow refering other users</p>
</div>
<div id="upload_container">
<input id="upload_permission_checkbox" name="upload" type="checkbox"></input>
<p>Allow uploading new files</p>
</div>
<div id="admin_container">
<input id="admin_permission_checkbox" name="manage" type="checkbox"></input>
<p>Allow administrative actions</p>
</div>
<input id="custom_message_text" name="message" placeholder="Custom message shown on signup page"></input>
<button type="submit">Generate referal link</button>
</form>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,24 @@
{% extends 'skel.html' %}
{% block body %}
<div id="mainwrapper">
<div id="contentarea">
<p id="infohead">
Sharing is <span style='text-decoration: line-through;'>communism</span> caring
</p>
<p id="infodisc">
Here's your shiny new referal link:
</p>
<input id="link_copy" readonly value="{{ url_for('signup', referalkey=key, _external=True) }}"></input>
</div>
</div>
<script>
document.querySelector('#link_copy').onclick = function(event) {
var sel, range;
sel = window.getSelection();
if(sel.toString() == '') {
event.target.select();
}
};
</script>
{% endblock %}

View File

@ -15,9 +15,14 @@
<body>
{% if current_user.is_authenticated %}
<div id="headerbar">
<a class="nostyle iconbutton" href="{{ url_for('logout') }}">
<a class="nostyle iconbutton" href="{{ url_for('logout') }}" title="Logout">
<i class="material-icons">exit_to_app</i>
</a>
{% if current_user.can_refer %}
<a class="nostyle iconbutton" href="{{ url_for('refer') }}" title="Add new user">
<i class="material-icons">person_add</i>
</a>
{% endif %}
<p id="headerbar-text">Appname</p>
</div>
{% endif %}