diff --git a/paramecio/libraries/db/formsutils.py b/paramecio/libraries/db/formsutils.py index 29f0653..b72046d 100644 --- a/paramecio/libraries/db/formsutils.py +++ b/paramecio/libraries/db/formsutils.py @@ -5,7 +5,7 @@ from paramecio.libraries.db.coreforms import PasswordForm from paramecio.libraries.i18n import I18n from paramecio.libraries.sessionplugin import get_session from paramecio.libraries.keyutils import create_key_encrypt -from bottle import request +from bottle import request, abort # Need unittest @@ -144,3 +144,13 @@ def request_type(): return request.environ['REQUEST_METHOD'] +def check_csrf(name_csrf_token='csrf_token'): + + session=get_session() + + csrf_token=session.get('csrf_token', '') + + if csrf_token=='' or csrf_token!=request.forms.get(name_csrf_token): + abort(403) + + diff --git a/paramecio/modules/admin2/app.py b/paramecio/modules/admin2/app.py index 2daaaca..d2a27eb 100644 --- a/paramecio/modules/admin2/app.py +++ b/paramecio/modules/admin2/app.py @@ -17,6 +17,8 @@ from paramecio.libraries.sessionplugin import SessionPlugin from paramecio.libraries.httputils import GetPostFiles from paramecio.libraries.db.formsutils import check_form, csrf_token from paramecio.libraries.db.coreforms import PasswordForm +from paramecio.libraries.sendmail import SendMail +from paramecio.libraries.db.formsutils import check_csrf admin_app=Bottle() admin_app.install(SessionPlugin()) @@ -138,6 +140,7 @@ def check_login_admin(session={}): username=getpost.post.get('username') password=getpost.post.get('password') remember_login=getpost.post.get('remember_login') + token_auth='' if username!='' and password!='' and not no_login: @@ -162,7 +165,20 @@ def check_login_admin(session={}): now_str=now() date_now=format_local_strtime('YYYY-MM-DD HH:mm:ss', now_str) - db.query('update useradmin2 set token_login=%s, last_login=%s WHERE id=%s', [remember_key, date_now, result['id']]) + token_auth='' + + if result['double_auth']: + + token_auth=create_key(8) + session['verify_auth']=True + + # Send email + + sendmail=SendMail(ssl=True) + + sendmail.send(config.portal_email, [result['email']], i18n.tlang('Code for complete login'), i18n.tlang('We send to you a code for activate your account using double authentication:')+"\n"+token_auth, content_type='plain', attachments=[]) + + db.query('update useradmin2 set token_login=%s, last_login=%s, token_auth=%s WHERE id=%s', [remember_key, date_now, usermodel.fields['password'].check(token_auth), result['id']]) session['login_admin']=True session['user_id']=result['id'] @@ -264,6 +280,59 @@ def change_theme(session={}): return {'error': error, 'message': ''} +@admin_app.get('/need_auth', skip=[check_login], name='admin_app.need_auth') +def need_auth(session={}): + + i18n=I18n('admin2') + + return t.load_template('need_auth.phtml', title=i18n.tlang('Auth check')) + +@admin_app.post('/auth_check', skip=[check_login], name='admin_app.auth_check') +def auth_check(session={}): + + error=1 + + #check_csrf() + + you_cannot_login=0 + + db=WebModel.connection() + + if 'login_admin' in session: + + code=request.forms.get('code', '') + + user_admin=UserAdmin2(db) + + user_admin.check_user=False + + arr_user=user_admin.set_conditions('WHERE id=%s', [session.get('user_id', 0)]).select_a_row_where() + #print(arr_user) + if arr_user: + + if user_admin.fields['token_auth'].verify(code, arr_user['token_auth']): + + user_admin.safe_query() + + #user_admin.set_conditions('WHERE id=%s', [session['user_id']]).update({'token_auth': ''}) + user_admin.query('update useradmin2 set token_auth="" WHERE id=%s', [session['user_id']]) + + session['verify_auth']=False + error=0 + + else: + + #you_cannot_login=check_login_tries() + you_cannot_login=check_login_tries(request, db) + + else: + + you_cannot_login=check_login_tries() + + db.close() + + return {'error': error, 'you_cannot_login': you_cannot_login} + def check_login_tries(request, db): diff --git a/paramecio/modules/admin2/ausers.py b/paramecio/modules/admin2/ausers.py index bcac440..08d801f 100644 --- a/paramecio/modules/admin2/ausers.py +++ b/paramecio/modules/admin2/ausers.py @@ -3,7 +3,7 @@ from paramecio.modules.admin2.app import admin_app from paramecio.modules.admin2.libraries.config import modules_admin, modules_admin_icons from paramecio.libraries.mtemplates import PTemplate, env_theme from paramecio.libraries.i18n import I18n -import paramecio.modules.admin2.libraries.i18n +import paramecio.modules.admin2.libraries.i18n as i18n_lang import os #from paramecio.libraries.lists import SimpleList from paramecio.libraries.generate_admin_class import GenerateAdminClass @@ -13,11 +13,14 @@ from paramecio.libraries.db.coreforms import PasswordForm from paramecio.wsgiapp import app from paramecio.libraries.db.webmodel import WebModel from paramecio.modules.admin2.models.admin import UserAdmin2 +from paramecio.libraries.urls import add_get_parameters env=env_theme(__file__) t=PTemplate(env) +i18n=I18n('admin2') + #t.env.directories=admin_t.env.directories """ tpl_path=os.path.dirname(__file__).replace('/admin', '')+'/templates/admin' @@ -45,11 +48,15 @@ def admin_users(session={}): user_admin.fields['dark_theme'].name_form=SelectForm - user_admin.create_forms(['username', 'password', 'email', 'privileges', 'lang', 'dark_theme']) + user_admin.fields['double_auth'].name_form=SelectForm + + user_admin.create_forms(['username', 'password', 'email', 'privileges', 'lang', 'dark_theme', 'double_auth']) user_admin.forms['privileges'].arr_select={0: I18n.lang('admin', 'without_privileges', 'Without privileges'), 1: I18n.lang('admin', 'selected_privileges', 'Selected privileges'), 2: I18n.lang('admin', 'administrator', 'Administrator')} - user_admin.forms['dark_theme'].arr_select={0: _('Light theme'), 1: _('Dark theme')} + user_admin.forms['dark_theme'].arr_select={0: i18n.tlang('Light theme'), 1: i18n.tlang('Dark theme')} + + user_admin.forms['double_auth'].arr_select={0: i18n.tlang('No'), 1: i18n.tlang('Yes')} user_admin.fields['password'].protected=False @@ -61,7 +68,9 @@ def admin_users(session={}): admin.list.search_fields=['username'] - admin.arr_fields_edit=['username', 'password', 'repeat_password', 'email', 'privileges', 'lang', 'dark_theme'] + admin.arr_fields_edit=['username', 'password', 'repeat_password', 'email', 'privileges', 'lang', 'dark_theme', 'double_auth'] + + admin.list.arr_extra_options=[user_options] slist=admin.show() @@ -69,4 +78,20 @@ def admin_users(session={}): return t.load_template('users.phtml', title=i18n.tlang('Admin users'), tlang=i18n.tlang, module_selected='admin_app.admin_users', slist=slist, session=session) +@admin_app.get('/ausers/permissions/', name="admin_app.admin_permissions") +def admin_users(user_id, session={}): + + db=WebModel.connection() + + db.close() + + return "" +def user_options(url, id, arr_row): + + options=[] + options.append(''+I18n.lang('common', 'edit', 'Edit')+'') + if not arr_row['privileges']: + options.append(f''+i18n.tlang('User access')+'') + options.append(''+I18n.lang('common', 'delete', 'Delete')+'') + return options diff --git a/paramecio/modules/admin2/libraries/loginplugin.py b/paramecio/modules/admin2/libraries/loginplugin.py index 085351f..4d6c4ad 100644 --- a/paramecio/modules/admin2/libraries/loginplugin.py +++ b/paramecio/modules/admin2/libraries/loginplugin.py @@ -8,12 +8,15 @@ def check_login(callback): if 'session' in request.environ: - if request.environ['session'].get('login_admin', 0): + if request.environ['session'].get('login_admin', False) and not request.environ['session'].get('verify_auth', False): result = callback(*args, **kwargs) return result - + + if request.environ['session'].get('verify_auth', False): + redirect(app.get_url('admin_app.need_auth')) + redirect(app.get_url('admin_app.login_admin')) return wrapper diff --git a/paramecio/modules/admin2/models/admin.py b/paramecio/modules/admin2/models/admin.py index a7654e1..a9b7fba 100644 --- a/paramecio/modules/admin2/models/admin.py +++ b/paramecio/modules/admin2/models/admin.py @@ -49,7 +49,9 @@ class UserAdmin2(UserModel): self.register(corefields.CharField('token_login')) - #self.register(PasswordField('token_auth')) + self.register(PasswordField('token_auth')) + + self.register(PasswordField('token_key')) self.register(PrivilegesField2('privileges')) diff --git a/paramecio/modules/admin2/templates/access.phtml b/paramecio/modules/admin2/templates/access.phtml new file mode 100644 index 0000000..cd5eed6 --- /dev/null +++ b/paramecio/modules/admin2/templates/access.phtml @@ -0,0 +1,4 @@ +<%inherit file="layout.phtml"/> +<%block name="content"> + + diff --git a/paramecio/modules/admin2/templates/need_auth.phtml b/paramecio/modules/admin2/templates/need_auth.phtml new file mode 100644 index 0000000..7819aaf --- /dev/null +++ b/paramecio/modules/admin2/templates/need_auth.phtml @@ -0,0 +1,197 @@ +<%inherit file="login.phtml"/> +<%block name="content"> +
+
+ ${tlang('Auth code')} +
+
+
+
+ + +
+ ${tlang('You need a valid code')} +
+
+ + ${csrf_token()|n} +
+
+ + + + + +<%block name="jscript"> + +