Added keyutils and fixes in autologin
This commit is contained in:
parent
cd0fdacbb7
commit
192e8b4b0b
4 changed files with 155 additions and 10 deletions
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
# A more simple set for make queries
|
||||
|
||||
def insert(model, dict_values, db):
|
||||
def insert(model, db, dict_values):
|
||||
|
||||
final_values={}
|
||||
|
||||
|
|
@ -25,3 +25,20 @@ def insert(model, dict_values, db):
|
|||
|
||||
return success
|
||||
|
||||
|
||||
def select(model, db, dict_fields=[], where_sql='', limit='', dict_values=[]):
|
||||
|
||||
if len(dict_fields)==0:
|
||||
dict_fields=['`'+field+'`' for field in model.fields.keys()]
|
||||
|
||||
str_fields=", ".join(dict_fields)
|
||||
|
||||
str_query='select {} from {} {} limit 1'.format(str_fields, model.name, where_sql)
|
||||
|
||||
arr_result=[]
|
||||
|
||||
with db.query(str_query, dict_values) as cursor:
|
||||
|
||||
arr_result=cursor.fetchall()
|
||||
|
||||
return arr_result
|
||||
|
|
|
|||
86
parameciofast/libraries/keyutils.py
Normal file
86
parameciofast/libraries/keyutils.py
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
"""
|
||||
Paramecio2fm is a series of wrappers for Flask, mako and others and construct a simple headless cms.
|
||||
|
||||
Copyright (C) 2023 Antonio de la Rosa Caballero
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
from hashlib import sha512, sha256
|
||||
from base64 import b64encode
|
||||
from os import urandom
|
||||
import string
|
||||
import secrets
|
||||
|
||||
# Functions for create random strings usando urandom
|
||||
|
||||
def create_key_encrypt(n=10):
|
||||
""" Simple function for create a random string
|
||||
|
||||
Simple function for create a random string based in sha512
|
||||
|
||||
Args:
|
||||
n (int): size of string random bytes (view urandom function in Python3 Help)
|
||||
"""
|
||||
|
||||
return sha512(urandom(n)).hexdigest()
|
||||
|
||||
def create_key_encrypt_256(n=10):
|
||||
|
||||
""" Simple function for create a random string
|
||||
|
||||
Simple function for create a random string based in sha256
|
||||
|
||||
Args:
|
||||
n (int): size of string random bytes (view urandom function in Python3 Help)
|
||||
"""
|
||||
|
||||
return sha256(urandom(n)).hexdigest()
|
||||
|
||||
def create_key(n=10):
|
||||
|
||||
""" Simple function for create a random string
|
||||
|
||||
Simple function for create a random string based in urandom function and base64 encoding
|
||||
|
||||
Args:
|
||||
n (int): size of string random bytes (view urandom function in Python3 Help)
|
||||
"""
|
||||
|
||||
rand_bytes=urandom(n)
|
||||
|
||||
return b64encode(rand_bytes).decode('utf-8')[0:-2]
|
||||
|
||||
def create_simple_password(n=14):
|
||||
|
||||
""" Based in python3 documentation for create passwords using secrets module
|
||||
|
||||
https://docs.python.org/3/library/secrets.html
|
||||
|
||||
Args:
|
||||
n (int): Number of random elements of the password
|
||||
|
||||
"""
|
||||
|
||||
password=''
|
||||
|
||||
alphabet=string.ascii_letters+string.digits+string.punctuation
|
||||
|
||||
while True:
|
||||
password=''.join(secrets.choice(alphabet) for i in range(n))
|
||||
if (any(c.islower() for c in password) and any(c.isupper() for c in password) and sum(c.isdigit() for c in password) >= 3):
|
||||
break
|
||||
|
||||
return password
|
||||
|
||||
|
|
@ -12,6 +12,8 @@ from parameciofast.libraries.fastutils import ResponseData
|
|||
from parameciofast.libraries.db import simplequery
|
||||
from settings import config
|
||||
from parameciofast.libraries.datetime import now, format_local_strtime, timestamp_to_datetime, obtain_timestamp
|
||||
from parameciofast.libraries.keyutils import create_key_encrypt, create_key
|
||||
from time import time
|
||||
|
||||
env=env_theme(__file__)
|
||||
t=PTemplate(env, app.url_path_for)
|
||||
|
|
@ -28,15 +30,16 @@ seconds_login=300
|
|||
if hasattr(config, 'seconds_login'):
|
||||
seconds_login=config.seconds_login
|
||||
|
||||
cookie_name='paramecio_session'
|
||||
|
||||
#useradmin.create_forms()
|
||||
|
||||
#useradmin.safe_query=True
|
||||
if hasattr(config, 'cookie_name'):
|
||||
cookie_name=config.cookie_name
|
||||
|
||||
@admin_app.get('/', response_class=HTMLResponse)
|
||||
def home_admin(request: Request, paramecio_session: Annotated[str | None, Cookie(description='Cookie for validate into the admin site. The cookie name can change in you settings/config.py')] = None, remote_address: Annotated[str | None, Header()] = None):
|
||||
|
||||
if not request.session.get('login_admin', None):
|
||||
|
||||
return RedirectResponse(app.url_path_for('login_admin'))
|
||||
|
||||
return "Hello world!"
|
||||
|
|
@ -47,6 +50,22 @@ def login_admin(request: Request):
|
|||
|
||||
db=WebModel.connection()
|
||||
|
||||
if cookie_name+'_remember' in request.cookies:
|
||||
|
||||
arr_user=simplequery.select(usermodel, db, dict_fields=['id', 'username'], where_sql='WHERE token_login=%s', dict_values=[request.cookies[cookie_name+'_remember']])
|
||||
|
||||
if len(arr_user)>0:
|
||||
now_str=now()
|
||||
date_now=format_local_strtime('YYYY-MM-DD HH:mm:ss', now_str)
|
||||
|
||||
db.query('update useradmin set last_login=%s WHERE id=%s', [date_now, arr_user[0]['id']])
|
||||
|
||||
request.session['login_admin']=True
|
||||
|
||||
db.close()
|
||||
|
||||
return RedirectResponse(app.url_path_for('home_admin'))
|
||||
|
||||
with db.query('select count(id) as num_users from useradmin', []) as cursor:
|
||||
num_users=cursor.fetchone()['num_users']
|
||||
|
||||
|
|
@ -85,7 +104,7 @@ class ResponseDataLogin(ResponseData):
|
|||
no_login: bool
|
||||
|
||||
@admin_app.post('/login')
|
||||
def check_login_admin(user: UserAdmin, request: Request) -> ResponseDataLogin:
|
||||
def check_login_admin(user: UserAdmin, request: Request, response: Response) -> ResponseDataLogin:
|
||||
|
||||
db=WebModel.connection()
|
||||
|
||||
|
|
@ -106,6 +125,22 @@ def check_login_admin(user: UserAdmin, request: Request) -> ResponseDataLogin:
|
|||
|
||||
if usermodel.fields['password'].verify(user.password, result['password']):
|
||||
|
||||
remember_key=''
|
||||
|
||||
if user.remember_login==True:
|
||||
# Send cookies
|
||||
|
||||
remember_key=create_key_encrypt()
|
||||
|
||||
timestamp=int(time())+315360000
|
||||
|
||||
response.set_cookie(key=cookie_name+'_remember', value=remember_key, expires=timestamp, max_age=315360000, httponly=True, path=config.application_root)
|
||||
|
||||
now_str=now()
|
||||
date_now=format_local_strtime('YYYY-MM-DD HH:mm:ss', now_str)
|
||||
|
||||
db.query('update useradmin set token_login=%s, last_login=%s WHERE id=%s', [remember_key, date_now, result['id']])
|
||||
|
||||
request.session['login_admin']=True
|
||||
error=0
|
||||
message=''
|
||||
|
|
@ -156,7 +191,7 @@ def signup_insert_admin(user: UserSignup, request: Request) -> ResponseData:
|
|||
|
||||
if not error:
|
||||
|
||||
if simplequery.insert(usermodel, dict(user), db):
|
||||
if simplequery.insert(usermodel, db, dict(user)):
|
||||
error=0
|
||||
message="User added!"
|
||||
|
||||
|
|
@ -168,10 +203,15 @@ def signup_insert_admin(user: UserSignup, request: Request) -> ResponseData:
|
|||
@admin_app.get('/logout')
|
||||
def logout_admin(request: Request) -> RedirectResponse:
|
||||
|
||||
response=RedirectResponse(app.url_path_for('login_admin'))
|
||||
|
||||
if 'login_admin' in request.session:
|
||||
del request.session['login_admin']
|
||||
|
||||
return RedirectResponse(app.url_path_for('login_admin'))
|
||||
if cookie_name+'_remember' in request.cookies:
|
||||
response.delete_cookie(cookie_name+'_remember', path=config.application_root)
|
||||
|
||||
return response
|
||||
|
||||
|
||||
def check_login_tries(request, db):
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="mb-3 form-check">
|
||||
<input type="checkbox" class="form-check-input" id="autologin" name="autologin">
|
||||
<label class="form-check-label" for="autologin">${tlang('Autologin')}</label>
|
||||
<input type="checkbox" class="form-check-input" id="remember_login_form" name="remember_login" value="1">
|
||||
<label class="form-check-label" for="autologin">${tlang('Remember login')}</label>
|
||||
</div>
|
||||
<button type="submit" id="login_submit" class="btn btn-primary">Submit</button>
|
||||
</form>
|
||||
|
|
@ -100,7 +100,9 @@
|
|||
|
||||
$('#login_submit').prop('disabled', true);
|
||||
|
||||
data_form={'username': $('#username_form').val(), 'password': $('#password_form').val(), 'csrf_token': $("#csrf_token").val(), 'remember_login': 0};
|
||||
const is_checked=document.getElementById('remember_login_form').checked;
|
||||
|
||||
data_form={'username': $('#username_form').val(), 'password': $('#password_form').val(), 'csrf_token': $("#csrf_token").val(), 'remember_login': is_checked};
|
||||
|
||||
$.ajax({
|
||||
url: "${url_for('check_login_admin')}",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue