Compare commits
29
Commits
cbb7ed4498
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f0097ac1b | ||
|
|
645edec125 | ||
|
|
253c5c2491 | ||
|
|
48be235fde | ||
|
|
5f3bbd0ff4 | ||
|
|
249b0009a3 | ||
|
|
5225f72ee0 | ||
|
|
de1315db33 | ||
|
|
6c2a65221c | ||
|
|
407fa6351d | ||
|
|
490e9bb80c | ||
|
|
c20a8a0b2c | ||
|
|
05821df546 | ||
|
|
3a88b7db3b | ||
|
|
a53f2aa274 | ||
|
|
92bc2bbdbf | ||
|
|
e2d0e7a95e | ||
|
|
9b4bd725da | ||
|
|
b783617335 | ||
|
|
4ea6831be2 | ||
|
|
b8645473a7 | ||
|
|
9cc6bf6290 | ||
|
|
4fe1bec588 | ||
|
|
f2ffabad3e | ||
|
|
7e7c599530 | ||
|
|
7a7edc1f92 | ||
|
|
078af33e77 | ||
|
|
94563bfefc | ||
|
|
da0114f2f8 |
+10
-3
@@ -1,9 +1,16 @@
|
||||
/settings.ini
|
||||
/settings.ini.example.original
|
||||
/uwsgi.ini
|
||||
/oharrak.txt
|
||||
/.env
|
||||
session
|
||||
libs/__pycache__
|
||||
__pycache__
|
||||
*.db
|
||||
!.empty
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
session
|
||||
static/tmp
|
||||
libs/__pycache__
|
||||
!static/tmp
|
||||
static/tmp/*
|
||||
!static/tmp/.gitkeep
|
||||
|
||||
+7
-2
@@ -1,6 +1,8 @@
|
||||
FROM python:3-alpine
|
||||
ARG UID_
|
||||
ENV UID_=1000
|
||||
|
||||
ARG USER_=admin
|
||||
ARG UID_=1000
|
||||
|
||||
RUN apk add --no-cache --upgrade bash
|
||||
|
||||
ADD --chown=$UID_:$UID_ . /www
|
||||
@@ -16,4 +18,7 @@ RUN set -e; \
|
||||
pip install -r requirements.txt; \
|
||||
apk del .build-deps;
|
||||
|
||||
RUN adduser -S -D $USER_ -u $UID_
|
||||
USER $USER_
|
||||
|
||||
ENTRYPOINT ["./start.sh"]
|
||||
|
||||
@@ -52,7 +52,7 @@ Konfiguraketa fitxategia sortu:
|
||||
|
||||
edo
|
||||
|
||||
docker build -t aitzol/ldap-webui:latest . --build-arg UID_=$UID
|
||||
docker build -t aitzol/ldap-webui:latest . --build-arg UID_=$UID --build-arg USER_=$USER
|
||||
|
||||
#### Edukiontzia sortu
|
||||
|
||||
|
||||
@@ -13,32 +13,34 @@
|
||||
|
||||
<body>
|
||||
<main>
|
||||
<h1>2FA</h1>
|
||||
<h1>{{ str['2fa-title'] }}</h1>
|
||||
|
||||
% if data['secureAuth'] == True:
|
||||
<div class="info">{{ str['2fa-info-1'] }}</div>
|
||||
<div class="qr-code">
|
||||
<img src="{{'static/tmp/'+data['authCode']+'.png'}}" />
|
||||
</div>
|
||||
<form name="disable2faForm" method="post" action="/disable_2fa">
|
||||
|
||||
<input id="2fa" name="2fa" type="text" value="{{data['authCode']}}" readonly>
|
||||
<label for="code">{{ str['code'] }}</label>
|
||||
<input id="" name="code" type="text" value="{{data['authCode']}}" readonly>
|
||||
|
||||
<div class="form-buttons">
|
||||
<a href="/user"><button class="green" type="button">{{ str['back'] }}</button></a>
|
||||
<button class="green" type="submit">Disable</button>
|
||||
<button class="green" type="submit">{{ str['disable'] }}</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
% else:
|
||||
|
||||
<div class="info">{{ str['2fa-info-2'] }}</div>
|
||||
<form name="enable2faForm" method="post" action="/enable_2fa">
|
||||
|
||||
<input id="2fa" name="2fa" type="text" value="{{data['authCode']}}" readonly>
|
||||
<!--<input id="token" name="token" type="text" value="{{data['authCode']}}" readonly>-->
|
||||
|
||||
<div class="form-buttons">
|
||||
<a href="/user"><button class="green" type="button">{{ str['back'] }}</button></a>
|
||||
<button class="green" type="submit">Enable</button>
|
||||
<button class="green" type="submit">{{ str['enable'] }}</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
@@ -19,9 +19,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
'''
|
||||
|
||||
import bottle
|
||||
from bottle import get, post, static_file, request, route, template
|
||||
from bottle import get, post, static_file, request, route, template, error
|
||||
from bottle import SimpleTemplate
|
||||
from bottle.ext import beaker
|
||||
#from bottle.ext import beaker
|
||||
from beaker.middleware import SessionMiddleware
|
||||
from configparser import ConfigParser
|
||||
from ldap3 import Server, Connection, ALL
|
||||
from ldap3 import SIMPLE, SUBTREE, MODIFY_REPLACE, MODIFY_ADD, MODIFY_DELETE, ALL_ATTRIBUTES
|
||||
@@ -37,11 +38,13 @@ from libs.helper import tools
|
||||
import random
|
||||
from user_agents import parse as ua_parse
|
||||
from datetime import datetime
|
||||
import cryptocode
|
||||
import base64
|
||||
|
||||
BASE_DIR = path.dirname(__file__)
|
||||
LOG = logging.getLogger(__name__)
|
||||
LOG_FORMAT = '%(asctime)s %(levelname)s: %(message)s'
|
||||
VERSION = '0.0.2'
|
||||
VERSION = '0.0.3'
|
||||
|
||||
@get('/')
|
||||
def get_index():
|
||||
@@ -53,7 +56,7 @@ def get_index():
|
||||
@get('/user')
|
||||
def get_index():
|
||||
try:
|
||||
print(newSession().get())
|
||||
print('SESSION:',newSession().get())
|
||||
return user_tpl(data=newSession().get(), str=i18n.str)
|
||||
except Exception as e:
|
||||
return index_tpl(str=i18n.str)
|
||||
@@ -119,10 +122,8 @@ def get_index():
|
||||
|
||||
@get('/_2fa')
|
||||
def get_index():
|
||||
#newSession().get()
|
||||
try:
|
||||
reload(newSession().get()['username'], None, None)
|
||||
#add_auth_attribute_step1(newSession().get()['username'], None, None)
|
||||
return _2fa_tpl(data=newSession().get(), str=i18n.str)
|
||||
except Exception as e:
|
||||
return index_tpl(str=i18n.str)
|
||||
@@ -156,10 +157,57 @@ def post_user():
|
||||
LOG.warning("Unsuccessful attempt to login %s: %s" % (form('username'), e))
|
||||
return error(str(e))
|
||||
|
||||
#if 2fa not chekced || (2fa checked & success)
|
||||
try:
|
||||
#if(check_2fa_step1(form('username'))):
|
||||
if(newSession().get()['secureAuth']):
|
||||
# encrypt and store the credentials
|
||||
key = tools.key()
|
||||
data = ';'.join([form('username'),form('password'),newSession().get()['authCode']])
|
||||
data_enc = cryptocode.encrypt(data, key)
|
||||
data_to_url = base64.urlsafe_b64encode(str.encode(data_enc))
|
||||
memo.data = data_enc
|
||||
memo.key = key
|
||||
logout(form('username'))
|
||||
return index_tpl(two_factor_authentication=True, path=data_to_url, str=i18n.str)
|
||||
except Error as e:
|
||||
#On error force disable 2fa
|
||||
add_auth_attribute_step1(form('username'), None, action='disable')
|
||||
LOG.debug("Two factor authentication has been impossible.")
|
||||
return error(i18n.msg[29])
|
||||
return user_tpl(alerts=[('success', '%s %s' % (i18n.msg[1], form('username').capitalize()), 'fadeOut' )], data=newSession().get(), str=i18n.str)
|
||||
#elif 2fa checked
|
||||
#return _2fa_tpl(alerts=[('success', '%s %s' % (i18n.msg[1], form('username').capitalize()), 'fadeOut' )], data=newSession().get(), str=i18n.str)
|
||||
|
||||
@post('/user/<path>')
|
||||
def post_user_step2(path):
|
||||
form = request.forms.getunicode
|
||||
|
||||
def error(msg):
|
||||
return index_tpl(alerts=[('error', msg, 'fadeOut')], str=i18n.str)
|
||||
|
||||
try:
|
||||
# decrypt url
|
||||
path = base64.urlsafe_b64decode(path)
|
||||
path = cryptocode.decrypt(path.decode('utf-8'), memo.key)
|
||||
data = path.split(';')
|
||||
|
||||
username = data[0]
|
||||
password = data[1]
|
||||
secret = data[2]
|
||||
except:
|
||||
newSession()
|
||||
return error(i18n.msg[27])
|
||||
|
||||
#if not tools._2fa_validation(form('token'), newSession().get()['authCode']):
|
||||
if not tools._2fa_validation(form('token'), secret):
|
||||
return error(i18n.msg[6])
|
||||
else:
|
||||
|
||||
try:
|
||||
login(username, password)
|
||||
except Error as e:
|
||||
LOG.warning("Unsuccessful attempt to login %s: %s" % (username, e))
|
||||
return error(str(e))
|
||||
|
||||
return user_tpl(alerts=[('success', '%s %s' % (i18n.msg[1], newSession().get()['username']), 'fadeOut' )], data=newSession().get(), str=i18n.str)
|
||||
|
||||
@post('/signup')
|
||||
def post_signup():
|
||||
@@ -183,7 +231,11 @@ def post_signup():
|
||||
def error(msg):
|
||||
return signup_tpl(alerts=[('error', msg, 'fadeOut')], str=i18n.str)
|
||||
|
||||
if not tools.code_is_valid(form('invite_code'), db):
|
||||
try:
|
||||
if not tools.code_is_valid(form('invite_code'), db):
|
||||
return(error(i18n.msg[6]))
|
||||
except Exception as e:
|
||||
LOG.error(e)
|
||||
return(error(i18n.msg[6]))
|
||||
|
||||
if len(form('username')) < 3:
|
||||
@@ -210,7 +262,7 @@ def post_signup():
|
||||
return error(i18n.msg[15])
|
||||
|
||||
if not tools.pwd_validation(form('password')):
|
||||
return error(i18n.msg[8]) #mezua ALDATU egin behar da
|
||||
return error(i18n.msg[8])
|
||||
elif form('password') != form('confirm-password'):
|
||||
return error(i18n.msg[7])
|
||||
|
||||
@@ -296,17 +348,16 @@ def post_enable_2fa():
|
||||
if(not newSession().get()['secureAuth']):
|
||||
try:
|
||||
username=newSession().get()['username']
|
||||
add_auth_attribute_step1(username, tools.generate_secret(), action='enable')
|
||||
add_auth_attribute_step1(username, tools.gen_secret(), action='enable')
|
||||
except Error as e:
|
||||
#add_auth_attribute_step1(newSession().get()['username'], None, None)
|
||||
reload(newSession().get()['username'], None, None)
|
||||
LOG.warning(e)
|
||||
return error('2 urratseko autentifikazioa birgaitua izan da.')
|
||||
return error(i18n.msg[30])
|
||||
except Error as e:
|
||||
LOG.warning(e)
|
||||
return index_tpl(alerts=[('error', e, 'fadeOut')], str=i18n.str)
|
||||
|
||||
return _2fa_tpl(alerts=[('success', 'Bikain, 2 urratseko autentifikazioa gaitu da.', 'fadeOut')], data=newSession().get(), str=i18n.str)
|
||||
return _2fa_tpl(alerts=[('success', i18n.msg[31], 'fadeOut')], data=newSession().get(), str=i18n.str)
|
||||
|
||||
@post('/disable_2fa')
|
||||
def post_disable_2fa():
|
||||
@@ -320,7 +371,6 @@ def post_disable_2fa():
|
||||
username=newSession().get()['username']
|
||||
add_auth_attribute_step1(username, None, action='disable')
|
||||
except Error as e:
|
||||
#add_auth_attribute_step1(newSession().get()['username'], None, None)
|
||||
reload(newSession().get()['username'], None, None)
|
||||
LOG.warning(e)
|
||||
return error(str(e))
|
||||
@@ -328,7 +378,7 @@ def post_disable_2fa():
|
||||
LOG.warning(e)
|
||||
return index_tpl(alerts=[('error', e, 'fadeOut')], str=i18n.str)
|
||||
|
||||
return _2fa_tpl(alerts=[('error', '2 urratseko autentifikazioa desgaitua izan da.', 'fadeOut')], data=newSession().get(), str=i18n.str)
|
||||
return _2fa_tpl(alerts=[('error', i18n.msg[32], 'fadeOut')], data=newSession().get(), str=i18n.str)
|
||||
|
||||
@post('/change_pwd')
|
||||
def post_change_pwd():
|
||||
@@ -388,11 +438,11 @@ def post_delete():
|
||||
def serve_static(filename):
|
||||
return static_file(filename, root=path.join(BASE_DIR, 'static'))
|
||||
|
||||
@get("/static/fonts/<filepath:re:.*\.(eot|otf|svg|ttf|woff|woff2?)>")
|
||||
@get("/static/fonts/<filepath:re:.*\\.(eot|otf|svg|ttf|woff|woff2?)>")
|
||||
def font(filepath):
|
||||
return static_file(filepath, root="static/fonts")
|
||||
|
||||
@get("/static/tmp/<filepath:re:.*\.(png|svg)>")
|
||||
@get("/static/tmp/<filepath:re:.*\\.(png|svg)>")
|
||||
def font(filepath):
|
||||
return static_file(filepath, root="static/tmp")
|
||||
|
||||
@@ -431,8 +481,14 @@ def connect_ldap(conf, **kwargs):
|
||||
|
||||
return Connection(server, raise_exceptions=True, **kwargs)
|
||||
|
||||
@error(404)
|
||||
@error(405)
|
||||
def error40x(error):
|
||||
return index_tpl(str=i18n.str)
|
||||
|
||||
#LOGIN
|
||||
def login(username, password):
|
||||
|
||||
n = N
|
||||
for key in (key for key in CONF.sections()
|
||||
if key == 'ldap' or key.startswith('ldap:')):
|
||||
@@ -447,7 +503,6 @@ def login(username, password):
|
||||
continue
|
||||
else:
|
||||
raise e
|
||||
|
||||
break
|
||||
|
||||
def login_user(conf, *args):
|
||||
@@ -480,6 +535,9 @@ def login_user_ldap(conf, username, password):
|
||||
#update timestamp + ip address
|
||||
update_login_info(conf, user_dn)
|
||||
LOG.debug("%s logged in to %s" % (username, conf['base']))
|
||||
#generate qr if it doenst exists when 2fa enable
|
||||
if(newSession().get()['secureAuth']):
|
||||
tools.gen_qr(newSession().get()['authCode'])
|
||||
|
||||
#LOGOUT
|
||||
def logout(username):
|
||||
@@ -598,7 +656,8 @@ def register(conf, username, firstname, surname, password, email, isFake, device
|
||||
firstname, 'sn': surname, 'uid' : username, 'mail': email, 'active': False, 'fakeCn': isFake,
|
||||
'devices':device, 'ip':request.environ.get('HTTP_X_REAL_IP', request.remote_addr), 'lastLogin': ts,
|
||||
'secureAuth': False}
|
||||
new_user_dn = "cn="+firstname+" "+surname+" - "+username+",cn=users,"+conf['base']
|
||||
#new_user_dn = "cn="+firstname+" "+surname+" - "+username+",cn=users,"+conf['base']
|
||||
new_user_dn = "cn="+firstname+" "+surname+",cn=users,"+conf['base']
|
||||
c.add(dn=new_user_dn,object_class=OBJECT_CLASS, attributes=attributes)
|
||||
#create/change user password
|
||||
c.extend.standard.modify_password(new_user_dn, '', password)
|
||||
@@ -732,10 +791,10 @@ def add_auth_attribute_step1(username, code, action):
|
||||
try:
|
||||
add_auth_attribute_step2(CONF[key], username, code, action)
|
||||
changed.append(key)
|
||||
LOG.debug("%s changed email address on %s" % (username, key))
|
||||
LOG.debug("%s has activated 2FA authentication on %s" % (username, key))
|
||||
except Error as e:
|
||||
for key in reversed(changed):
|
||||
LOG.info("Reverting email change in %s for %s" % (key, username))
|
||||
LOG.info("Reverting 2FA activation in %s for %s due to errors" % (key, username))
|
||||
try:
|
||||
new_email_address(CONF[key], username, new_email, old_email)
|
||||
except Error as e2:
|
||||
@@ -760,18 +819,16 @@ def add_auth_attribute_step2(conf, *args):
|
||||
|
||||
except LDAPNoSuchAttributeResult as e:
|
||||
LOG.error('{}: {!s}'.format(e.__class__.__name__, e))
|
||||
raise Error('Dagoeneko desgaiturik zeneukan 2 urratseko autentifikazioa.')
|
||||
raise Error(i18n.msg[33])
|
||||
|
||||
except LDAPExceptionError as e:
|
||||
LOG.error('{}: {!s}'.format(e.__class__.__name__, e))
|
||||
raise Error(i18n.msg[23])
|
||||
|
||||
def add_auth_attribute_step3(conf, username, code, action):
|
||||
|
||||
#set current LDAP
|
||||
superUser = SuperUsers(conf)
|
||||
|
||||
print(action)
|
||||
with connect_ldap(conf, user=superUser.admin_dn, password=superUser.admin_pwd) as c:
|
||||
user_dn = find_user_dn(conf, c, username)
|
||||
if(action == 'enable'):
|
||||
@@ -952,6 +1009,12 @@ def get_user_email_array(user_dn, conn, old_email, new_email):
|
||||
emails[i] = new_email
|
||||
return(emails)
|
||||
|
||||
def check_secure_auth(user_dn, conn):
|
||||
search_filter = '(objectClass=*)'
|
||||
conn.search(user_dn, search_filter, attributes=['secureAuth'])
|
||||
status = conn.entries[0].secureAuth
|
||||
return(status)
|
||||
|
||||
def get_user_data(user_dn, conn):
|
||||
search_filter = '(objectClass=*)'
|
||||
conn.search(user_dn, search_filter,
|
||||
@@ -965,11 +1028,17 @@ def get_user_data(user_dn, conn):
|
||||
data.append(conn.entries[0].uid.values[0])
|
||||
data.append(conn.entries[0].mail.values[0])
|
||||
data.append(conn.entries[0].devices.values)
|
||||
data.append(conn.entries[0].ip.values[0])
|
||||
if(conn.entries[0].ip):
|
||||
data.append(conn.entries[0].ip.values[0])
|
||||
else:
|
||||
data.append(request.environ.get('HTTP_X_REAL_IP', request.remote_addr))
|
||||
#ts = conn.entries[0].lastLogin.values[0]
|
||||
#ts = datetime.strptime(ts, '%Y-%m-%d %H:%M:%S%z')
|
||||
#ts = datetime.strftime(t, '%Y-%m-%d %H:%M:%S')
|
||||
data.append(str(conn.entries[0].lastLogin.values[0])[:-6])
|
||||
if(conn.entries[0].lastLogin):
|
||||
data.append(str(conn.entries[0].lastLogin.values[0])[:-6])
|
||||
else:
|
||||
data.append(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
|
||||
data.append(conn.entries[0].secureAuth.values[0])
|
||||
if(conn.entries[0].authCode):
|
||||
data.append(conn.entries[0].authCode.values[0])
|
||||
@@ -1012,18 +1081,10 @@ def is_trusted_device(conf, user_dn):
|
||||
if not find_device(user_dn, c, d):
|
||||
OBJECT_CLASS = ['top', 'inetOrgPerson', 'posixAccount', 'accountsManagement']
|
||||
c.modify(user_dn, {'devices': [( MODIFY_ADD, d )] })
|
||||
'''
|
||||
if find_device(user_dn, c, 'unknown'):
|
||||
OBJECT_CLASS = ['top', 'inetOrgPerson', 'posixAccount', 'accountsManagement']
|
||||
c.modify(user_dn, {'devices': [( MODIFY_REPLACE, d )] })
|
||||
else:
|
||||
OBJECT_CLASS = ['top', 'inetOrgPerson', 'posixAccount', 'accountsManagement']
|
||||
c.modify(user_dn, {'devices': [( MODIFY_ADD, d )] })
|
||||
'''
|
||||
c.unbind()
|
||||
return True
|
||||
except Exception as e:
|
||||
print(e)
|
||||
LOG.warning(e)
|
||||
return True
|
||||
|
||||
def update_login_info(conf, user_dn):
|
||||
@@ -1037,6 +1098,14 @@ def update_login_info(conf, user_dn):
|
||||
class Error(Exception):
|
||||
pass
|
||||
|
||||
# TEMPORAL MEMORY
|
||||
class tMemory(object):
|
||||
def __init__(self):
|
||||
self.data = None
|
||||
self.key = None
|
||||
|
||||
memo = tMemory()
|
||||
|
||||
#SESSIONS MANAGEMENT
|
||||
def newSession():
|
||||
|
||||
@@ -1045,7 +1114,7 @@ def newSession():
|
||||
def __init__(self):
|
||||
super(Session, self).__init__()
|
||||
self.data = bottle.request.environ.get('beaker.session')
|
||||
self.lang = self.get_lang()
|
||||
self.sid = self.data.id
|
||||
#localization
|
||||
self.lang = self.get_lang()
|
||||
global i18n
|
||||
@@ -1092,6 +1161,8 @@ def newSession():
|
||||
self.data['secureAuth'] = self.secureAuth
|
||||
self.data['authCode'] = self.authCode
|
||||
|
||||
self.data['id'] = self.sid
|
||||
|
||||
def close(self):
|
||||
self.data.pop('username')
|
||||
|
||||
@@ -1128,7 +1199,8 @@ class SuperUsers(object):
|
||||
|
||||
superUser = SuperUsers(CONF['ldap:0'])
|
||||
|
||||
app = beaker.middleware.SessionMiddleware(bottle.app(), session_opts)
|
||||
#app = beaker.middleware.SessionMiddleware(bottle.app(), session_opts)
|
||||
app = SessionMiddleware(bottle.app(), session_opts)
|
||||
|
||||
bottle.TEMPLATE_PATH = [BASE_DIR]
|
||||
|
||||
|
||||
Binary file not shown.
@@ -15,12 +15,21 @@
|
||||
<main>
|
||||
<h1>{{ str['login'] }}</h1>
|
||||
|
||||
<form method="post" action="/user">
|
||||
<label for="username">{{ str['usrn'] }}</label>
|
||||
<input id="username" name="username" value="{{ get('username', '') }}" type="text" required autofocus>
|
||||
%try:
|
||||
%if two_factor_authentication:
|
||||
<form method="post" action="/user/{{path}}">
|
||||
<label for="token">{{ str['token'] }}</label>
|
||||
<input id="token" name="token" value="" type="text" required autofocus>
|
||||
%end
|
||||
%except:
|
||||
<form method="post" action="/user">
|
||||
<label for="username">{{ str['usrn'] }}</label>
|
||||
<input id="username" name="username" value="{{ get('username', '') }}" type="text" required autofocus>
|
||||
|
||||
<label for="password">{{ str['pwd'] }}</label>
|
||||
<input id="password" name="password" type="password" pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*_=+-]).{8,24}$" oninvalid="setCustomValidity('{{ str['pwd-pattern'] }}')" oninput="setCustomValidity('')" required>
|
||||
<label for="password">{{ str['pwd'] }}</label>
|
||||
<input id="password" name="password" type="password" pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%^&*_=+-]).{8,24}$" oninvalid="setCustomValidity('{{ str['pwd-pattern'] }}')" oninput="setCustomValidity('')" required>
|
||||
|
||||
%end
|
||||
|
||||
<button class="green" type="submit">{{str['login']}}</button>
|
||||
<a href="/signup">{{ str['or-sign-up'] }}</a>
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
from onetimepass import valid_totp
|
||||
from secrets import choice
|
||||
|
||||
|
||||
def generate_secret(): # Function to return a random string with length 16.
|
||||
secret = ''
|
||||
while len(secret) < 16:
|
||||
secret += choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567')
|
||||
return secret
|
||||
|
||||
|
||||
secret = generate_secret()
|
||||
print('Enter the following secret in your authenticator app: ', secret)
|
||||
print("""
|
||||
Instructions for saving this secret it Google Authenticator:
|
||||
1. Open Google Authenticator.
|
||||
2. Click plus icon at the right bottom.
|
||||
3. Click Enter a setup key.
|
||||
4. Enter an Account name of your choice and enter the secret provided above.
|
||||
5. Click Add.
|
||||
""")
|
||||
while True:
|
||||
otp = int(input('Please enter the otp generated by your authenticator app: '))
|
||||
authenticated = valid_totp(otp, secret)
|
||||
if authenticated:
|
||||
print('Correct otp, Authenticated!')
|
||||
elif not authenticated:
|
||||
print('Wrong otp, please try again.')
|
||||
|
||||
+21
-3
@@ -5,6 +5,8 @@ import re
|
||||
from onetimepass import valid_totp
|
||||
from secrets import choice
|
||||
import segno
|
||||
from os import path
|
||||
import uuid
|
||||
|
||||
class Tools():
|
||||
|
||||
@@ -47,12 +49,28 @@ class Tools():
|
||||
return(bool(re.fullmatch(regex, e)))
|
||||
|
||||
# 2FA
|
||||
def generate_secret(self): # Function to return a random string with length 16.
|
||||
def gen_qr(self, secret):
|
||||
if(not path.isfile('static/tmp/'+secret+'.png')):
|
||||
qrcode = segno.make(secret, micro=False)
|
||||
qrcode.save('static/tmp/'+secret+'.png', scale=10)
|
||||
|
||||
def gen_secret(self): # Function to return a random string with length 16.
|
||||
secret = ''
|
||||
while len(secret) < 16:
|
||||
secret += choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567')
|
||||
qrcode = segno.make(secret, micro=False)
|
||||
qrcode.save('static/tmp/'+secret+'.png', scale=10)
|
||||
self.gen_qr(secret)
|
||||
return secret
|
||||
|
||||
def _2fa_validation(self, otp, secret):
|
||||
authenticated = valid_totp(otp, secret)
|
||||
if authenticated:
|
||||
print('Correct otp, Authenticated!')
|
||||
return True
|
||||
elif not authenticated:
|
||||
print('Wrong otp, please try again.')
|
||||
return False
|
||||
|
||||
def key(self):
|
||||
return uuid.uuid4().hex
|
||||
|
||||
tools = Tools()
|
||||
|
||||
+17
-2
@@ -40,6 +40,13 @@ class LocalizeTo(object):
|
||||
str_25 = _("Last login")
|
||||
str_26 = _("Devices")
|
||||
str_27 = _("show")
|
||||
str_28 = _("Two factor authentication")
|
||||
str_29 = _("Token")
|
||||
str_30 = _("Disable")
|
||||
str_31 = _("Enable")
|
||||
str_32 = _("You must then use the key created by this QR code to log in. To get the key you must use a OTP or 2FA mobile app.")
|
||||
str_33 = _("Two-step authentication is additional security. By enabling this you will be asked at the login, in addition to the user and password, a key you will need to create using QR code.")
|
||||
str_34 = _("Code")
|
||||
|
||||
#messages
|
||||
msg_00 = _("The session was closed.")
|
||||
@@ -71,11 +78,19 @@ class LocalizeTo(object):
|
||||
msg_26 = _("Forgot your password? Please try again.")
|
||||
msg_27 = _("The session has expired.")
|
||||
msg_28 = _("Registration is currently closed. We apologize for the inconvenience.")
|
||||
msg_29 = _("Two factor authentication has been impossible.")
|
||||
msg_30 = _("Two factor authentication has been restored.")
|
||||
msg_31 = _("Two factor authentication has been enabled.")
|
||||
msg_32 = _("Two factor authentication has been disabled.")
|
||||
msg_33 = _("Two factor authentication was already disabled.")
|
||||
|
||||
self.str = {'usr':str_00, 'usrn':str_01, 'fn':str_02, 'sn':str_03, 'pwd':str_04, 'old-pwd':str_05,
|
||||
'new-pwd':str_06, 'conf-pwd':str_07, 'email':str_08, 'edit':str_09, 'login':str_10, 'log-out':str_11,
|
||||
'del':str_12, 'sign-up':str_13, 'back':str_14, 'update':str_15, 'or-sign-in':str_16,
|
||||
'or-sign-up':str_17, 'inv-code':str_18, 'edit-fn':str_19, 'edit-email':str_20, 'ch-pwd':str_21,
|
||||
'del-account':str_22, 'welcome':str_23, 'logs':str_24, 'last-login':str_25, 'devices':str_26,
|
||||
'show':str_27, 'pwd-pattern': msg_08}
|
||||
self.msg = (msg_00, msg_01, msg_02, msg_03, msg_04, msg_05, msg_06, msg_07, msg_08, msg_09, msg_10, msg_11, msg_12, msg_13, msg_14, msg_15, msg_16, msg_17, msg_18, msg_19, msg_20, msg_21, msg_22, msg_23, msg_24, msg_25, msg_26, msg_27, msg_28)
|
||||
'show':str_27, '2fa-title':str_28, 'token':str_29, 'disable':str_30, 'enable':str_31, '2fa-info-1':str_32,
|
||||
'2fa-info-2':str_33, 'code':str_34, 'pwd-pattern': msg_08}
|
||||
self.msg = (msg_00, msg_01, msg_02, msg_03, msg_04, msg_05, msg_06, msg_07, msg_08, msg_09, msg_10, msg_11,
|
||||
msg_12, msg_13, msg_14, msg_15, msg_16, msg_17, msg_18, msg_19, msg_20, msg_21, msg_22, msg_23,
|
||||
msg_24, msg_25, msg_26, msg_27, msg_28, msg_29, msg_30, msg_31, msg_32, msg_33)
|
||||
|
||||
+140
-98
@@ -6,243 +6,285 @@
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Project-Id-Version: 0.0.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-04-25 16:52+0200\n"
|
||||
"POT-Creation-Date: 2023-11-27 15:52+0100\n"
|
||||
"PO-Revision-Date: 2023-04-07 13:28+0200\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=CHARSET\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 3.2.2\n"
|
||||
|
||||
#: libs/localization.py:15
|
||||
msgid "User"
|
||||
msgstr "User"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:16
|
||||
msgid "Username"
|
||||
msgstr "Username"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:17
|
||||
msgid "Firstname"
|
||||
msgstr "Firstname"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:18
|
||||
msgid "Surname"
|
||||
msgstr "Surname"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:19
|
||||
msgid "Password"
|
||||
msgstr "Password"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:20
|
||||
msgid "Old password"
|
||||
msgstr "Old password"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:21
|
||||
msgid "New password"
|
||||
msgstr "New password"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:22
|
||||
msgid "Confirm password"
|
||||
msgstr "Confirm password"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:23
|
||||
msgid "Email"
|
||||
msgstr "Email"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:24
|
||||
msgid "edit"
|
||||
msgstr "edit"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:25
|
||||
msgid "Login"
|
||||
msgstr "Login"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:26
|
||||
msgid "Logout"
|
||||
msgstr "Logout"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:27
|
||||
msgid "Delete"
|
||||
msgstr "Delete"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:28
|
||||
msgid "Sign Up"
|
||||
msgstr "Sign Up"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:29
|
||||
msgid "Back"
|
||||
msgstr "Back"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:30
|
||||
msgid "Update"
|
||||
msgstr "Update"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:31
|
||||
msgid "Or Sign In"
|
||||
msgstr "Or Sign In"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:32
|
||||
msgid "Or Sign Up"
|
||||
msgstr "Or Sign Up"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:33
|
||||
msgid "Invite code"
|
||||
msgstr "Invite code"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:34
|
||||
msgid "Edit your fullname"
|
||||
msgstr "Edit your fullname"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:35
|
||||
msgid "Edit your email"
|
||||
msgstr "Edit your email"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:36
|
||||
msgid "Change your password"
|
||||
msgstr "Change your password"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:37
|
||||
msgid "Delete your account"
|
||||
msgstr "Delete your account"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:38 libs/localization.py:46
|
||||
#: libs/localization.py:38 libs/localization.py:53
|
||||
msgid "Welcome"
|
||||
msgstr "Welcome"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:39
|
||||
msgid "Logs"
|
||||
msgstr "Logs"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:40
|
||||
msgid "Last login"
|
||||
msgstr "Last login"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:41
|
||||
msgid "Devices"
|
||||
msgstr "Devices"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:42
|
||||
msgid "show"
|
||||
msgstr "show"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:43
|
||||
msgid "Two factor authentication"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:44
|
||||
msgid "Token"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:45
|
||||
msgid "The session was closed."
|
||||
msgstr "The session was closed."
|
||||
msgid "Disable"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:46
|
||||
msgid "Enable"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:47
|
||||
msgid "Username must be at least 3 characters long!"
|
||||
msgstr "Username must be at least 3 characters long!"
|
||||
msgid "You must then use the key created by this QR code to log in. To get the key you must use a OTP or 2FA mobile app."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:48
|
||||
msgid "Not allowed characters for the username field."
|
||||
msgstr "Not allowed characters for the username field."
|
||||
msgid "Two-step authentication is additional security. By enabling this you will be asked at the login, in addition to the user and password, a key you will need to create using QR code."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:49
|
||||
msgid "Not allowed characters for the firstname field."
|
||||
msgstr "Not allowed characters for the firstname field."
|
||||
|
||||
#: libs/localization.py:50
|
||||
msgid "Not allowed characters for the surname field."
|
||||
msgstr "Not allowed characters for the surname field."
|
||||
|
||||
#: libs/localization.py:51
|
||||
msgid "The code is invalid or has expired."
|
||||
msgstr "The code is invalid or has expired."
|
||||
msgid "Code"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:52
|
||||
msgid "Passwords do not match!"
|
||||
msgstr "Passwords do not match!"
|
||||
|
||||
#: libs/localization.py:53
|
||||
msgid ""
|
||||
"The password must contain at least 8 characters, at least one number, "
|
||||
"a capital letter and a special character."
|
||||
msgid "The session was closed."
|
||||
msgstr ""
|
||||
"The password must contain at least 8 characters, at least one number, "
|
||||
"a capital letter and a special character."
|
||||
|
||||
#: libs/localization.py:54
|
||||
msgid "Congratulations, your account has been created!"
|
||||
msgstr "Congratulations, your account has been created!"
|
||||
msgid "Username must be at least 3 characters long!"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:55
|
||||
msgid "Your first and last name have not been changed."
|
||||
msgstr "Your first and last name have not been changed."
|
||||
msgid "Not allowed characters for the username field."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:56
|
||||
msgid "Your firstname is a bit short, don't you think?"
|
||||
msgstr "Your firstname is a bit short, don't you think?"
|
||||
msgid "Not allowed characters for the firstname field."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:57
|
||||
msgid "Your surname is a bit short, don't you think?"
|
||||
msgstr "Your surname is a bit short, don't you think?"
|
||||
msgid "Not allowed characters for the surname field."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:58
|
||||
msgid "Your first and last name have been successfully updated."
|
||||
msgstr "Your first and last name have been successfully updated."
|
||||
msgid "The code is invalid or has expired."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:59
|
||||
msgid "Invalid email address. Please try again."
|
||||
msgstr "Invalid email address. Please try again."
|
||||
msgid "Passwords do not match!"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:60
|
||||
msgid "Email address has not been changed."
|
||||
msgstr "Email address has not been changed."
|
||||
msgid "The password must contain at least 8 characters, at least one number, a capital letter and a special character."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:61
|
||||
msgid "Your email has been successfully updated."
|
||||
msgstr "Your email has been successfully updated."
|
||||
msgid "Congratulations, your account has been created!"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:62
|
||||
msgid "The password entered is the same as the current password."
|
||||
msgstr "The password entered is the same as the current password."
|
||||
msgid "Your first and last name have not been changed."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:63
|
||||
msgid "Password has been changed!"
|
||||
msgstr "Password has been changed!"
|
||||
msgid "Your firstname is a bit short, don't you think?"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:64
|
||||
msgid "Please, type your username for account deletion."
|
||||
msgstr "Please, type your username for account deletion."
|
||||
msgid "Your surname is a bit short, don't you think?"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:65
|
||||
msgid "Account successfully deleted!"
|
||||
msgstr "Account successfully deleted!"
|
||||
msgid "Your first and last name have been successfully updated."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:66
|
||||
msgid "Username or password is incorrect!"
|
||||
msgstr "Username or password is incorrect!"
|
||||
msgid "Invalid email address. Please try again."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:67
|
||||
msgid "Unable to connect to the remote server."
|
||||
msgstr "Unable to connect to the remote server."
|
||||
msgid "Email address has not been changed."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:68
|
||||
msgid ""
|
||||
"Encountered an unexpected error while communicating with the remote server."
|
||||
msgid "Your email has been successfully updated."
|
||||
msgstr ""
|
||||
"Encountered an unexpected error while communicating with the remote server."
|
||||
|
||||
#: libs/localization.py:69
|
||||
msgid "User already exists."
|
||||
msgstr "User already exists."
|
||||
msgid "The password entered is the same as the current password."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:70
|
||||
msgid "Email already exists."
|
||||
msgstr "Email already exists."
|
||||
msgid "Password has been changed!"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:71
|
||||
msgid "Forgot your password? Please try again."
|
||||
msgstr "Forgot your password? Please try again."
|
||||
msgid "Please, type your username for account deletion."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:72
|
||||
msgid "The session has expired."
|
||||
msgstr "The session has expired."
|
||||
msgid "Account successfully deleted!"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:73
|
||||
msgid "Username or password is incorrect!"
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:74
|
||||
msgid "Unable to connect to the remote server."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:75
|
||||
msgid "Encountered an unexpected error while communicating with the remote server."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:76
|
||||
msgid "User already exists."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:77
|
||||
msgid "Email already exists."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:78
|
||||
msgid "Forgot your password? Please try again."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:79
|
||||
msgid "The session has expired."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:80
|
||||
msgid "Registration is currently closed. We apologize for the inconvenience."
|
||||
msgstr "Registration is currently closed. We apologize for the inconvenience."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:81
|
||||
msgid "Two factor authentication has been impossible."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:82
|
||||
msgid "Two factor authentication has been restored."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:83
|
||||
msgid "Two factor authentication has been enabled."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:84
|
||||
msgid "Two factor authentication has been disabled."
|
||||
msgstr ""
|
||||
|
||||
#: libs/localization.py:85
|
||||
msgid "Two factor authentication was already disabled."
|
||||
msgstr ""
|
||||
|
||||
Binary file not shown.
@@ -1,21 +1,21 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <aitzol@lainoa.eus>, 2022.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: 0.0.1\n"
|
||||
"Project-Id-Version: 0.0.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-04-07 17:20+0200\n"
|
||||
"PO-Revision-Date: 2023-04-07 13:28+0200\n"
|
||||
"Last-Translator: Aitzol Berasategi <aitzol@lainoa.eus>\n"
|
||||
"Language-Team: LANGUAGE <EN@en.org>\n"
|
||||
"POT-Creation-Date: 2022-04-25 16:52+0200\n"
|
||||
"PO-Revision-Date: 2023-11-27 15:37+0100\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: \n"
|
||||
"Language: en\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.3\n"
|
||||
"X-Generator: Poedit 3.2.2\n"
|
||||
|
||||
#: libs/localization.py:15
|
||||
msgid "User"
|
||||
@@ -109,7 +109,7 @@ msgstr "Change your password"
|
||||
msgid "Delete your account"
|
||||
msgstr "Delete your account"
|
||||
|
||||
#: libs/localization.py:38 libs/localization.py:46
|
||||
#: libs/localization.py:38 libs/localization.py:53
|
||||
msgid "Welcome"
|
||||
msgstr "Welcome"
|
||||
|
||||
@@ -129,120 +129,162 @@ msgstr "Devices"
|
||||
msgid "show"
|
||||
msgstr "show"
|
||||
|
||||
#: libs/localization.py:43
|
||||
msgid "Two factor authentication"
|
||||
msgstr "Two factor authentication"
|
||||
|
||||
#: libs/localization.py:44
|
||||
msgid "Token"
|
||||
msgstr "Token"
|
||||
|
||||
#: libs/localization.py:45
|
||||
msgid "Disable"
|
||||
msgstr "Disable"
|
||||
|
||||
#: libs/localization.py:46
|
||||
msgid "Enable"
|
||||
msgstr "Enable"
|
||||
|
||||
#: libs/localization.py:47
|
||||
msgid "You must then use the key created by this QR code to log in. To get the key you must use a OTP or 2FA mobile app."
|
||||
msgstr "You must then use the key created by this QR code to log in. To get the key you must use a OTP or 2FA mobile app."
|
||||
|
||||
#: libs/localization.py:48
|
||||
msgid "Two-step authentication is additional security. By enabling this you will be asked at the login, in addition to the user and password, a key you will need to create using QR code."
|
||||
msgstr "Two-step authentication is additional security. By enabling this you will be asked at the login, in addition to the user and password, a key you will need to create using QR code."
|
||||
|
||||
#: libs/localization.py:49
|
||||
msgid "Code"
|
||||
msgstr "Code"
|
||||
|
||||
#: libs/localization.py:52
|
||||
msgid "The session was closed."
|
||||
msgstr "The session was closed."
|
||||
|
||||
#: libs/localization.py:47
|
||||
#: libs/localization.py:54
|
||||
msgid "Username must be at least 3 characters long!"
|
||||
msgstr "Username must be at least 3 characters long!"
|
||||
|
||||
#: libs/localization.py:48
|
||||
#: libs/localization.py:55
|
||||
msgid "Not allowed characters for the username field."
|
||||
msgstr "Not allowed characters for the username field."
|
||||
|
||||
#: libs/localization.py:49
|
||||
#: libs/localization.py:56
|
||||
msgid "Not allowed characters for the firstname field."
|
||||
msgstr "Not allowed characters for the firstname field."
|
||||
|
||||
#: libs/localization.py:50
|
||||
#: libs/localization.py:57
|
||||
msgid "Not allowed characters for the surname field."
|
||||
msgstr "Not allowed characters for the surname field."
|
||||
|
||||
#: libs/localization.py:51
|
||||
#: libs/localization.py:58
|
||||
msgid "The code is invalid or has expired."
|
||||
msgstr "The code is invalid or has expired."
|
||||
|
||||
#: libs/localization.py:52
|
||||
#: libs/localization.py:59
|
||||
msgid "Passwords do not match!"
|
||||
msgstr "Passwords do not match!"
|
||||
|
||||
#: libs/localization.py:53
|
||||
msgid ""
|
||||
"The password must contain at least 8 characters, at least one number, "
|
||||
"a capital letter and a special character."
|
||||
msgstr ""
|
||||
"The password must contain at least 8 characters, at least one number, "
|
||||
"a capital letter and a special character."
|
||||
#: libs/localization.py:60
|
||||
msgid "The password must contain at least 8 characters, at least one number, a capital letter and a special character."
|
||||
msgstr "The password must contain at least 8 characters, at least one number, a capital letter and a special character."
|
||||
|
||||
#: libs/localization.py:54
|
||||
#: libs/localization.py:61
|
||||
msgid "Congratulations, your account has been created!"
|
||||
msgstr "Congratulations, your account has been created!"
|
||||
|
||||
#: libs/localization.py:55
|
||||
#: libs/localization.py:62
|
||||
msgid "Your first and last name have not been changed."
|
||||
msgstr "Your first and last name have not been changed."
|
||||
|
||||
#: libs/localization.py:56
|
||||
#: libs/localization.py:63
|
||||
msgid "Your firstname is a bit short, don't you think?"
|
||||
msgstr "Your firstname is a bit short, don't you think?"
|
||||
|
||||
#: libs/localization.py:57
|
||||
#: libs/localization.py:64
|
||||
msgid "Your surname is a bit short, don't you think?"
|
||||
msgstr "Your surname is a bit short, don't you think?"
|
||||
|
||||
#: libs/localization.py:58
|
||||
#: libs/localization.py:65
|
||||
msgid "Your first and last name have been successfully updated."
|
||||
msgstr "Your first and last name have been successfully updated."
|
||||
|
||||
#: libs/localization.py:59
|
||||
#: libs/localization.py:66
|
||||
msgid "Invalid email address. Please try again."
|
||||
msgstr "Invalid email address. Please try again."
|
||||
|
||||
#: libs/localization.py:60
|
||||
#: libs/localization.py:67
|
||||
msgid "Email address has not been changed."
|
||||
msgstr "Email address has not been changed."
|
||||
|
||||
#: libs/localization.py:61
|
||||
#: libs/localization.py:68
|
||||
msgid "Your email has been successfully updated."
|
||||
msgstr "Your email has been successfully updated."
|
||||
|
||||
#: libs/localization.py:62
|
||||
#: libs/localization.py:69
|
||||
msgid "The password entered is the same as the current password."
|
||||
msgstr "The password entered is the same as the current password."
|
||||
|
||||
#: libs/localization.py:63
|
||||
#: libs/localization.py:70
|
||||
msgid "Password has been changed!"
|
||||
msgstr "Password has been changed!"
|
||||
|
||||
#: libs/localization.py:64
|
||||
#: libs/localization.py:71
|
||||
msgid "Please, type your username for account deletion."
|
||||
msgstr "Please, type your username for account deletion."
|
||||
|
||||
#: libs/localization.py:65
|
||||
#: libs/localization.py:72
|
||||
msgid "Account successfully deleted!"
|
||||
msgstr "Account successfully deleted!"
|
||||
|
||||
#: libs/localization.py:66
|
||||
#: libs/localization.py:73
|
||||
msgid "Username or password is incorrect!"
|
||||
msgstr "Username or password is incorrect!"
|
||||
|
||||
#: libs/localization.py:67
|
||||
#: libs/localization.py:74
|
||||
msgid "Unable to connect to the remote server."
|
||||
msgstr "Unable to connect to the remote server."
|
||||
|
||||
#: libs/localization.py:68
|
||||
msgid ""
|
||||
"Encountered an unexpected error while communicating with the remote server."
|
||||
msgstr ""
|
||||
"Encountered an unexpected error while communicating with the remote server."
|
||||
#: libs/localization.py:75
|
||||
msgid "Encountered an unexpected error while communicating with the remote server."
|
||||
msgstr "Encountered an unexpected error while communicating with the remote server."
|
||||
|
||||
#: libs/localization.py:69
|
||||
#: libs/localization.py:76
|
||||
msgid "User already exists."
|
||||
msgstr "User already exists."
|
||||
|
||||
#: libs/localization.py:70
|
||||
#: libs/localization.py:77
|
||||
msgid "Email already exists."
|
||||
msgstr "Email already exists."
|
||||
|
||||
#: libs/localization.py:71
|
||||
#: libs/localization.py:78
|
||||
msgid "Forgot your password? Please try again."
|
||||
msgstr "Forgot your password? Please try again."
|
||||
|
||||
#: libs/localization.py:72
|
||||
#: libs/localization.py:79
|
||||
msgid "The session has expired."
|
||||
msgstr "The session has expired."
|
||||
|
||||
#: libs/localization.py:73
|
||||
#: libs/localization.py:80
|
||||
msgid "Registration is currently closed. We apologize for the inconvenience."
|
||||
msgstr "Registration is currently closed. We apologize for the inconvenience."
|
||||
|
||||
#: libs/localization.py:81
|
||||
msgid "Two factor authentication has been impossible."
|
||||
msgstr "Two factor authentication has been impossible."
|
||||
|
||||
#: libs/localization.py:82
|
||||
msgid "Two factor authentication has been restored."
|
||||
msgstr "Two factor authentication has been restored."
|
||||
|
||||
#: libs/localization.py:83
|
||||
msgid "Two factor authentication has been enabled."
|
||||
msgstr "Two factor authentication has been enabled."
|
||||
|
||||
#: libs/localization.py:84
|
||||
msgid "Two factor authentication has been disabled."
|
||||
msgstr "Two factor authentication has been disabled."
|
||||
|
||||
#: libs/localization.py:85
|
||||
msgid "Two factor authentication was already disabled."
|
||||
msgstr "Two factor authentication was already disabled."
|
||||
|
||||
Binary file not shown.
@@ -5,17 +5,17 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: 0.0.1\n"
|
||||
"Project-Id-Version: 0.0.3\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-04-07 17:23+0200\n"
|
||||
"PO-Revision-Date: 2023-04-07 13:27+0200\n"
|
||||
"PO-Revision-Date: 2023-11-27 15:36+0100\n"
|
||||
"Last-Translator: Aitzol Berasategi <aitzol@lainoa.eus>\n"
|
||||
"Language-Team: LANGUAGE <EU@eu.org>\n"
|
||||
"Language: eu\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 2.3\n"
|
||||
"X-Generator: Poedit 3.2.2\n"
|
||||
|
||||
#: libs/localization.py:15
|
||||
msgid "User"
|
||||
@@ -109,7 +109,7 @@ msgstr "Pasahitza eguneratu"
|
||||
msgid "Delete your account"
|
||||
msgstr "Kontua ezabatu"
|
||||
|
||||
#: libs/localization.py:38 libs/localization.py:46
|
||||
#: libs/localization.py:38 libs/localization.py:53
|
||||
msgid "Welcome"
|
||||
msgstr "Ongi etorri"
|
||||
|
||||
@@ -129,119 +129,162 @@ msgstr "Gailuak"
|
||||
msgid "show"
|
||||
msgstr "ikusi"
|
||||
|
||||
#: libs/localization.py:43
|
||||
msgid "Two factor authentication"
|
||||
msgstr "Bi urratseko autentifikazioa"
|
||||
|
||||
#: libs/localization.py:44
|
||||
msgid "Token"
|
||||
msgstr "Gakoa"
|
||||
|
||||
#: libs/localization.py:45
|
||||
msgid "Disable"
|
||||
msgstr "Desgaitu"
|
||||
|
||||
#: libs/localization.py:46
|
||||
msgid "Enable"
|
||||
msgstr "Gaitu"
|
||||
|
||||
#: libs/localization.py:47
|
||||
msgid "You must then use the key created by this QR code to log in. To get the key you must use a OTP or 2FA mobile app."
|
||||
msgstr "Aurrerantzean QR kode honen bidez sortutako gakoa erabili beharko duzu saioa hasteko. Gakoa lortzeko mugikorrerako OTP edo 2FA aplikazio bat erabili beharko duzu."
|
||||
|
||||
#: libs/localization.py:48
|
||||
msgid "Two-step authentication is additional security. By enabling this you will be asked at the login, in addition to the user and password, a key you will need to create using QR code."
|
||||
msgstr "Bi urratseko autentifikazioa segurtasun gehigarri bat da. Hau gaituz saio hasieran erabiltzaile eta pasahitzaz gain QR kode bidez sortu beharko duzun gako bat eskatuko zaizu."
|
||||
|
||||
#: libs/localization.py:49
|
||||
msgid "Code"
|
||||
msgstr "Kodea"
|
||||
|
||||
#: libs/localization.py:52
|
||||
msgid "The session was closed."
|
||||
msgstr "Saioa itxi da."
|
||||
|
||||
#: libs/localization.py:47
|
||||
#: libs/localization.py:54
|
||||
msgid "Username must be at least 3 characters long!"
|
||||
msgstr "Erabiltzaile izenak gutxienez 3 karaktere izan behar ditu!"
|
||||
|
||||
#: libs/localization.py:48
|
||||
#: libs/localization.py:55
|
||||
msgid "Not allowed characters for the username field."
|
||||
msgstr "Erabiltzaile-izenaren eremurako onartzen ez diren karaktereak."
|
||||
|
||||
#: libs/localization.py:49
|
||||
#: libs/localization.py:56
|
||||
msgid "Not allowed characters for the firstname field."
|
||||
msgstr "Izenaren eremurako onartzen ez diren karaktereak."
|
||||
|
||||
#: libs/localization.py:50
|
||||
#: libs/localization.py:57
|
||||
msgid "Not allowed characters for the surname field."
|
||||
msgstr "Abizenaren eremurako onartzen ez diren karaktereak."
|
||||
|
||||
#: libs/localization.py:51
|
||||
#: libs/localization.py:58
|
||||
msgid "The code is invalid or has expired."
|
||||
msgstr "Kodea baliogabea da edo iraungi egin da."
|
||||
|
||||
#: libs/localization.py:52
|
||||
#: libs/localization.py:59
|
||||
msgid "Passwords do not match!"
|
||||
msgstr "Pasahitzak ez datoz bat!"
|
||||
|
||||
#: libs/localization.py:53
|
||||
msgid ""
|
||||
"The password must contain at least 8 characters, at least one number, "
|
||||
"a capital letter and a special character."
|
||||
msgstr ""
|
||||
"Pasahitzak gutxienez 8 karaktere izan behar ditu, zenbaki bat, hizki larri bat "
|
||||
"eta karaktere berezi bat."
|
||||
#: libs/localization.py:60
|
||||
msgid "The password must contain at least 8 characters, at least one number, a capital letter and a special character."
|
||||
msgstr "Pasahitzak gutxienez 8 karaktere izan behar ditu, zenbaki bat, hizki larri bat eta karaktere berezi bat."
|
||||
|
||||
#: libs/localization.py:54
|
||||
#: libs/localization.py:61
|
||||
msgid "Congratulations, your account has been created!"
|
||||
msgstr "Zorionak, zure kontua sortu da!"
|
||||
|
||||
#: libs/localization.py:55
|
||||
#: libs/localization.py:62
|
||||
msgid "Your first and last name have not been changed."
|
||||
msgstr "Zure izen-abizenak ez dira aldatu."
|
||||
|
||||
#: libs/localization.py:56
|
||||
#: libs/localization.py:63
|
||||
msgid "Your firstname is a bit short, don't you think?"
|
||||
msgstr "Zure izena labur-xamarra da, ez duzu uste?"
|
||||
|
||||
#: libs/localization.py:57
|
||||
#: libs/localization.py:64
|
||||
msgid "Your surname is a bit short, don't you think?"
|
||||
msgstr "Zure abizena labur-xamarra da, ez duzu uste?"
|
||||
|
||||
#: libs/localization.py:58
|
||||
#: libs/localization.py:65
|
||||
msgid "Your first and last name have been successfully updated."
|
||||
msgstr "Zure izen-abizenak ongi eguneratu dira."
|
||||
|
||||
#: libs/localization.py:59
|
||||
#: libs/localization.py:66
|
||||
msgid "Invalid email address. Please try again."
|
||||
msgstr "Baliogabeko email helbidea. Saia zaitez berriz, mesedez."
|
||||
|
||||
#: libs/localization.py:60
|
||||
#: libs/localization.py:67
|
||||
msgid "Email address has not been changed."
|
||||
msgstr "Email helbidea ez da aldatu."
|
||||
|
||||
#: libs/localization.py:61
|
||||
#: libs/localization.py:68
|
||||
msgid "Your email has been successfully updated."
|
||||
msgstr "Zure emaila ongi eguneratu da."
|
||||
|
||||
#: libs/localization.py:62
|
||||
#: libs/localization.py:69
|
||||
msgid "The password entered is the same as the current password."
|
||||
msgstr "Sartutako pasahitza egungo pasahitzaren berdina da."
|
||||
|
||||
#: libs/localization.py:63
|
||||
#: libs/localization.py:70
|
||||
msgid "Password has been changed!"
|
||||
msgstr "Pasahitza eguneratua izan da!"
|
||||
|
||||
#: libs/localization.py:64
|
||||
#: libs/localization.py:71
|
||||
msgid "Please, type your username for account deletion."
|
||||
msgstr "Kontua ezabatzeko idatzi zure erabiltzaile izena, mesedez."
|
||||
|
||||
#: libs/localization.py:65
|
||||
#: libs/localization.py:72
|
||||
msgid "Account successfully deleted!"
|
||||
msgstr "Kontua ongi ezabatu da!"
|
||||
|
||||
#: libs/localization.py:66
|
||||
#: libs/localization.py:73
|
||||
msgid "Username or password is incorrect!"
|
||||
msgstr "Erabiltzaile izena edo pasahitza okerrak dira!"
|
||||
|
||||
#: libs/localization.py:67
|
||||
#: libs/localization.py:74
|
||||
msgid "Unable to connect to the remote server."
|
||||
msgstr "Ezinezkoa urruneko zerbitzara konektatzea."
|
||||
|
||||
#: libs/localization.py:68
|
||||
msgid ""
|
||||
"Encountered an unexpected error while communicating with the remote server."
|
||||
#: libs/localization.py:75
|
||||
msgid "Encountered an unexpected error while communicating with the remote server."
|
||||
msgstr "Ezusteko errore bat gertatu da urruneko zerbitzariarekin komunikatzean."
|
||||
|
||||
#: libs/localization.py:69
|
||||
#: libs/localization.py:76
|
||||
msgid "User already exists."
|
||||
msgstr "Erabiltzaile hori existitzen da."
|
||||
|
||||
#: libs/localization.py:70
|
||||
#: libs/localization.py:77
|
||||
msgid "Email already exists."
|
||||
msgstr "Email hori existitzen da."
|
||||
|
||||
#: libs/localization.py:71
|
||||
#: libs/localization.py:78
|
||||
msgid "Forgot your password? Please try again."
|
||||
msgstr "Zure pasahitza ahaztu duzu? Saia zeitez berriz, mesedez."
|
||||
|
||||
#: libs/localization.py:72
|
||||
#: libs/localization.py:79
|
||||
msgid "The session has expired."
|
||||
msgstr "Saioa iraungi egin da."
|
||||
|
||||
#: libs/localization.py:73
|
||||
#: libs/localization.py:80
|
||||
msgid "Registration is currently closed. We apologize for the inconvenience."
|
||||
msgstr "Izen-ematea itxita dago une honetan. Barkatu eragozpenak."
|
||||
|
||||
#: libs/localization.py:81
|
||||
msgid "Two factor authentication has been impossible."
|
||||
msgstr "Ezinezkoa izan da bi urratseko autentifikazioa burutzea."
|
||||
|
||||
#: libs/localization.py:82
|
||||
msgid "Two factor authentication has been restored."
|
||||
msgstr "Bi urratseko autentifikazioa birgaitua izan da."
|
||||
|
||||
#: libs/localization.py:83
|
||||
msgid "Two factor authentication has been enabled."
|
||||
msgstr "Bi urratseko autentifikazioa gaitua izan da."
|
||||
|
||||
#: libs/localization.py:84
|
||||
msgid "Two factor authentication has been disabled."
|
||||
msgstr "Bi urratseko autentifikazioa desgaitua izan da."
|
||||
|
||||
#: libs/localization.py:85
|
||||
msgid "Two factor authentication was already disabled."
|
||||
msgstr "Bi urratseko autentifikazioa desgaiturik zegoen."
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
Beaker>=1.12.1
|
||||
bottle>=0.12.19
|
||||
bottle-beaker>=0.1.3
|
||||
ldap3>=2.9.1
|
||||
@@ -5,3 +6,6 @@ uwsgi>=2.0.21
|
||||
pyyaml>=6.0
|
||||
ua-parser>=0.16.1
|
||||
user-agents>=2.2.0
|
||||
cryptocode==0.1
|
||||
onetimepass==1.0.1
|
||||
segno==1.5.3
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#!/bin/bash
|
||||
##############################
|
||||
## Erabilera: ##
|
||||
## sudo chmod +x start.sh ##
|
||||
## ./start.sh $UID ##
|
||||
##############################
|
||||
#!/bin/bash
|
||||
if [ ! -f settings.ini ]; then
|
||||
cp settings.ini.example settings.ini
|
||||
fi
|
||||
@@ -11,8 +11,11 @@ fi
|
||||
if [[ $# -gt 0 ]]; then
|
||||
UID_=$1
|
||||
echo $UID_
|
||||
export LDAP_ADMIN_PASSWORD=admin
|
||||
export LDAP_READONLY_PASSWORD=readonly
|
||||
else
|
||||
UID_=$UID
|
||||
fi
|
||||
|
||||
export LDAP_ADMIN_PASSWORD=admin
|
||||
export LDAP_READONLY_PASSWORD=readonly
|
||||
|
||||
uwsgi --http :9090 --enable-threads --uid $UID_ --wsgi-file app.py
|
||||
|
||||
@@ -201,6 +201,15 @@ button.red:hover{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
.info {
|
||||
margin: 0 auto;
|
||||
max-width: 24rem;
|
||||
padding: 0 2.5rem 0 2.5rem;
|
||||
text-align: justify;
|
||||
}
|
||||
|
||||
/**/
|
||||
.grid-container {
|
||||
display: grid;
|
||||
@@ -234,6 +243,15 @@ button.red:hover{
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.info {
|
||||
max-width: 16rem;
|
||||
}
|
||||
}
|
||||
@media only screen and (min-width: 481px) and (max-width: 760px) {
|
||||
|
||||
.info {
|
||||
max-width: 22rem;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
<div class="grid-item">
|
||||
<div class="account">
|
||||
<h5>2FA</h5>
|
||||
<p>Bi urratseko autentifikazioa</p>
|
||||
<p>{{ str['2fa-title'] }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -4,5 +4,6 @@
|
||||
http = :8080
|
||||
chdir = %v
|
||||
wsgi-file = %v/app.py
|
||||
enable-thread = true
|
||||
processes = 1
|
||||
threads = 2
|
||||
|
||||
Reference in New Issue
Block a user