Update login

Add profile
This commit is contained in:
RemiZOffAlex
2019-04-26 19:38:23 +03:00
parent bba7df52d2
commit 1e9ac7eb97
17 changed files with 237 additions and 46 deletions

View File

@@ -26,9 +26,31 @@ formatter = logging.Formatter(app.config['LONG_LOG_FORMAT'])
handler.setFormatter(formatter)
app.logger.addHandler(handler)
from . import lib, models
@app.context_processor
def inject_data():
result = {}
result['user'] = None
if lib.get_user():
result['user'] = lib.get_user()
return result
@app.teardown_appcontext
def shutdown_session(exception=None):
models.db_session.close_all()
# API
from . import ns_api
# Авторизация
from . import ns_login
# Профиль
from . import ns_profile
# Пользователи
from . import ns_user

36
myapp/decorators.py Normal file
View File

@@ -0,0 +1,36 @@
#!/usr/bin/env python3
__author__ = 'RemiZOffAlex'
__copyright__ = '(c) RemiZOffAlex'
__license__ = 'MIT'
__email__ = 'remizoffalex@mail.ru'
__url__ = 'http://remizoffalex.ru'
import datetime
from functools import wraps
from flask import session, redirect
from . import models
def login_required(func):
@wraps(func)
def decorated_function(*args, **kwargs):
if 'logged_in' in session and 'user_id' in session:
user = models.db_session.query(
models.User
).filter(
models.User.id==session['user_id']
).first()
if user:
user.last_activity = datetime.datetime.now()
models.db_session.commit()
return func(*args, **kwargs)
else:
session.pop('logged_in', None)
session.pop('user_id', None)
return redirect('/login')
else:
return redirect('/login')
return decorated_function

View File

@@ -7,6 +7,6 @@ __url__ = 'https://remizoffalex.ru'
from .pagination import Pagination, getpage
from .passwd import pwgen, get_hash_password
from .storage import gettree, gethashtree
from .info import get_user, get_ip
from .info import get_user
__all__ = []

View File

@@ -23,14 +23,3 @@ def get_user():
session.pop('user_id', None)
return None
return result
def get_ip():
"""
Получить IP
"""
result = ''
if request.headers.getlist("X-Forwarded-For"):
result = request.headers.get("X-Forwarded-For").split(",")[0]
else:
result = request.remote_addr
return result

View File

@@ -1,35 +1,32 @@
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
__author__ = 'RemiZOffAlex'
__copyright__ = '(c) RemiZOffAlex'
__license__ = 'MIT'
__email__ = 'remizoffalex@mail.ru'
__url__ = 'https://remizoffalex.ru'
import uuid
import random
import hashlib
from .. import app
def pwgen(length=15, hex=False):
"""
Генератор пароля
"""
keylist='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
keylist = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
if hex:
keylist='0123456789ABCDEF'
password=[]
keylist = '0123456789ABCDEF'
password = []
while len(password) < length:
a_char = random.choice(keylist)
password.append(a_char)
return ''.join(password)
def get_hash_password(password, salt = None):
def get_hash_password(password, salt=None):
"""
Получить хеш пароля SHA-512
"""
if salt == None:
if salt is None:
salt = uuid.uuid4().hex
text = password.encode('utf-8') + salt.encode('utf-8')
h = hashlib.sha512()

View File

@@ -0,0 +1,18 @@
__author__ = 'RemiZOffAlex'
__copyright__ = '(c) RemiZOffAlex'
__license__ = 'MIT'
__email__ = 'remizoffalex@mail.ru'
__url__ = 'https://remizoffalex.ru'
import os
import jinja2
from . import views
from .. import app
my_loader = jinja2.ChoiceLoader([
app.jinja_loader,
jinja2.FileSystemLoader(os.path.dirname(os.path.abspath(__file__)) + "/templates"),
])
app.jinja_loader = my_loader

17
myapp/ns_login/forms.py Normal file
View File

@@ -0,0 +1,17 @@
__author__ = 'RemiZOffAlex'
__copyright__ = '(c) RemiZOffAlex'
__license__ = 'MIT'
__email__ = 'remizoffalex@mail.ru'
__url__ = 'http://remizoffalex.ru'
from wtforms import (
validators,
Form,
StringField,
PasswordField
)
class LoginForm(Form):
username = StringField('Логин', [validators.Length(min=4, max=25)])
password = PasswordField('Пароль', [validators.DataRequired()])

View File

@@ -2,10 +2,9 @@
{% block body %}
<div class="col-md-6 ml-auto mr-auto">
<div class="card">
<div class="card-header">Логин</div>
<h3>Логин</h3>
<hr />
<div class="card-body">
<form class="form-horizontal" action="/login" method="post" autocomplete="on">
<div style="margin-bottom: 25px" class="input-group">
@@ -25,7 +24,5 @@
</form>
</div>
</div>
</div>
{% endblock %}

45
myapp/ns_login/views.py Normal file
View File

@@ -0,0 +1,45 @@
__author__ = 'RemiZOffAlex'
__copyright__ = '(c) RemiZOffAlex'
__license__ = 'MIT'
__email__ = 'remizoffalex@mail.ru'
__url__ = 'https://remizoffalex.ru'
from flask import render_template, escape, request, session, redirect
from .. import app, lib, models
from . import forms
@app.route('/login', methods=['GET', 'POST'])
def login():
"""
Логин
"""
pagedata = {}
pagedata['form'] = forms.LoginForm(request.form)
if request.method == 'POST':
if pagedata['form'].validate():
user = models.db_session.query(
models.User
).filter(
models.User.name == escape(pagedata['form'].username.data),
models.User.password == lib.get_hash_password(
escape(pagedata['form'].password.data),
app.config['SECRET_KEY']
),
models.User.disabled == False
).first()
if user:
session['logged_in'] = True
session['user_id'] = user.id
return redirect('/', code=302)
body = render_template('login.html', pagedata=pagedata)
return body
@app.route('/logout')
def logout():
session.pop('logged_in', None)
session.pop('user_id', None)
return redirect("/", code=302)

View File

@@ -0,0 +1,18 @@
__author__ = 'RemiZOffAlex'
__copyright__ = '(c) RemiZOffAlex'
__license__ = 'MIT'
__email__ = 'remizoffalex@mail.ru'
__url__ = 'http://remizoffalex.ru'
import os
import jinja2
from . import views
from .. import app
my_loader = jinja2.ChoiceLoader([
app.jinja_loader,
jinja2.FileSystemLoader(os.path.dirname(os.path.abspath(__file__)) + "/templates"),
])
app.jinja_loader = my_loader

View File

@@ -0,0 +1,9 @@
{% extends "skeleton.html" %}
{% block body %}
<h3>Профиль</h3>
<hr />
<p>Зарегистрирован: {{ user.created.strftime('%Y-%m-%d') }}</p>
{% endblock body %}

22
myapp/ns_profile/views.py Normal file
View File

@@ -0,0 +1,22 @@
__author__ = 'RemiZOffAlex'
__copyright__ = '(c) RemiZOffAlex'
__license__ = 'MIT'
__email__ = 'remizoffalex@mail.ru'
__url__ = 'http://remizoffalex.ru'
from flask import render_template
from .. import app
from ..decorators import login_required
@app.route('/profile')
@login_required
def profile():
"""
Личный профиль пользователя
"""
pagedata = {}
pagedata['title'] = 'Мой профиль - {}'.format(app.config['TITLE'])
body = render_template('profile.html', pagedata=pagedata)
return body

View File

@@ -13,14 +13,28 @@
<div class="form-group">
{{ pagedata['form'].text.label }}
{{ pagedata['form'].text(class="form-control") }}
<script>
CKEDITOR.replace( 'text', {
customConfig: '/static/js/ckeditor-conf.js'
} );
</script>
</div>
<button class="btn btn-outline-success float-right"><i class="fa fa-save-o"></i> Сохранить</button>
</form>
{% endblock %}
{% block script %}
<script type="text/javascript" src="/static/ckeditor/ckeditor.js"></script>
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
},
methods: {
},
mounted: function () {
CKEDITOR.replace( 'text', {
customConfig: '/static/js/ckeditor-conf.js'
} );
}
})
</script>
{% endblock %}

View File

@@ -1,5 +1,14 @@
<div class="container-fluid py-2">
{% if session.logged_in %}
<div class="btn-group float-right">
<a class="btn btn-outline-secondary border-0" href="/profile"><i class="fa fa-user"></i></a>
<a class="btn btn-outline-danger border-0" href="/logout"><i class="fa fa-sign-out"></i></a>
</div>
{% else %}
<a class="btn btn-outline-success border-0 float-right" href="/login"><i class="fa fa-sign-in"></i></a>
{% endif %}
<a class="btn btn-outline-secondary border-0" href="/"><i class="fa fa-home"></i></a>
<a class="btn btn-outline-secondary border-0" href="/edit"><i class="fa fa-edit"></i> Редактор</a>
<a class="btn btn-outline-secondary border-0" href="/users">Vue & axios</a>

View File

@@ -5,4 +5,4 @@
{{ pagedata['text']|safe }}
{% endblock %}
{% endblock body %}

View File

@@ -8,12 +8,21 @@
<div class="container">
{% block body %}
{% endblock %}
{% endblock body %}
</div>
</section>
{% block script %}
{% endblock %}
<script type="text/javascript">
var app = new Vue({
el: '#app',
data: {
},
methods: {
}
})
</script>
{% endblock script %}
</body>
</html>

View File

@@ -39,14 +39,3 @@ def edit():
return body
body = render_template('edit.html', pagedata=pagedata)
return body
@app.route('/login', methods=['GET', 'POST'])
def login():
"""
Логин
"""
pagedata = {}
pagedata['form'] = forms.LoginForm(request.form)
body = render_template('login.html', pagedata=pagedata)
return body