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
|
||||||
/settings.ini.example.original
|
/settings.ini.example.original
|
||||||
/uwsgi.ini
|
/uwsgi.ini
|
||||||
|
/oharrak.txt
|
||||||
|
/.env
|
||||||
|
session
|
||||||
|
libs/__pycache__
|
||||||
|
__pycache__
|
||||||
|
*.db
|
||||||
|
!.empty
|
||||||
*.swp
|
*.swp
|
||||||
*.swo
|
*.swo
|
||||||
*~
|
*~
|
||||||
session
|
!static/tmp
|
||||||
static/tmp
|
static/tmp/*
|
||||||
libs/__pycache__
|
!static/tmp/.gitkeep
|
||||||
|
|||||||
+7
-2
@@ -1,6 +1,8 @@
|
|||||||
FROM python:3-alpine
|
FROM python:3-alpine
|
||||||
ARG UID_
|
|
||||||
ENV UID_=1000
|
ARG USER_=admin
|
||||||
|
ARG UID_=1000
|
||||||
|
|
||||||
RUN apk add --no-cache --upgrade bash
|
RUN apk add --no-cache --upgrade bash
|
||||||
|
|
||||||
ADD --chown=$UID_:$UID_ . /www
|
ADD --chown=$UID_:$UID_ . /www
|
||||||
@@ -16,4 +18,7 @@ RUN set -e; \
|
|||||||
pip install -r requirements.txt; \
|
pip install -r requirements.txt; \
|
||||||
apk del .build-deps;
|
apk del .build-deps;
|
||||||
|
|
||||||
|
RUN adduser -S -D $USER_ -u $UID_
|
||||||
|
USER $USER_
|
||||||
|
|
||||||
ENTRYPOINT ["./start.sh"]
|
ENTRYPOINT ["./start.sh"]
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ Konfiguraketa fitxategia sortu:
|
|||||||
|
|
||||||
edo
|
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
|
#### Edukiontzia sortu
|
||||||
|
|
||||||
|
|||||||
@@ -13,32 +13,34 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<main>
|
<main>
|
||||||
<h1>2FA</h1>
|
<h1>{{ str['2fa-title'] }}</h1>
|
||||||
|
|
||||||
% if data['secureAuth'] == True:
|
% if data['secureAuth'] == True:
|
||||||
|
<div class="info">{{ str['2fa-info-1'] }}</div>
|
||||||
<div class="qr-code">
|
<div class="qr-code">
|
||||||
<img src="{{'static/tmp/'+data['authCode']+'.png'}}" />
|
<img src="{{'static/tmp/'+data['authCode']+'.png'}}" />
|
||||||
</div>
|
</div>
|
||||||
<form name="disable2faForm" method="post" action="/disable_2fa">
|
<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">
|
<div class="form-buttons">
|
||||||
<a href="/user"><button class="green" type="button">{{ str['back'] }}</button></a>
|
<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>
|
</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
% else:
|
% else:
|
||||||
|
<div class="info">{{ str['2fa-info-2'] }}</div>
|
||||||
<form name="enable2faForm" method="post" action="/enable_2fa">
|
<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">
|
<div class="form-buttons">
|
||||||
<a href="/user"><button class="green" type="button">{{ str['back'] }}</button></a>
|
<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>
|
</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
@@ -19,9 +19,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
import bottle
|
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 import SimpleTemplate
|
||||||
from bottle.ext import beaker
|
#from bottle.ext import beaker
|
||||||
|
from beaker.middleware import SessionMiddleware
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
from ldap3 import Server, Connection, ALL
|
from ldap3 import Server, Connection, ALL
|
||||||
from ldap3 import SIMPLE, SUBTREE, MODIFY_REPLACE, MODIFY_ADD, MODIFY_DELETE, ALL_ATTRIBUTES
|
from ldap3 import SIMPLE, SUBTREE, MODIFY_REPLACE, MODIFY_ADD, MODIFY_DELETE, ALL_ATTRIBUTES
|
||||||
@@ -37,11 +38,13 @@ from libs.helper import tools
|
|||||||
import random
|
import random
|
||||||
from user_agents import parse as ua_parse
|
from user_agents import parse as ua_parse
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
import cryptocode
|
||||||
|
import base64
|
||||||
|
|
||||||
BASE_DIR = path.dirname(__file__)
|
BASE_DIR = path.dirname(__file__)
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
LOG_FORMAT = '%(asctime)s %(levelname)s: %(message)s'
|
LOG_FORMAT = '%(asctime)s %(levelname)s: %(message)s'
|
||||||
VERSION = '0.0.2'
|
VERSION = '0.0.3'
|
||||||
|
|
||||||
@get('/')
|
@get('/')
|
||||||
def get_index():
|
def get_index():
|
||||||
@@ -53,7 +56,7 @@ def get_index():
|
|||||||
@get('/user')
|
@get('/user')
|
||||||
def get_index():
|
def get_index():
|
||||||
try:
|
try:
|
||||||
print(newSession().get())
|
print('SESSION:',newSession().get())
|
||||||
return user_tpl(data=newSession().get(), str=i18n.str)
|
return user_tpl(data=newSession().get(), str=i18n.str)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return index_tpl(str=i18n.str)
|
return index_tpl(str=i18n.str)
|
||||||
@@ -119,10 +122,8 @@ def get_index():
|
|||||||
|
|
||||||
@get('/_2fa')
|
@get('/_2fa')
|
||||||
def get_index():
|
def get_index():
|
||||||
#newSession().get()
|
|
||||||
try:
|
try:
|
||||||
reload(newSession().get()['username'], None, None)
|
reload(newSession().get()['username'], None, None)
|
||||||
#add_auth_attribute_step1(newSession().get()['username'], None, None)
|
|
||||||
return _2fa_tpl(data=newSession().get(), str=i18n.str)
|
return _2fa_tpl(data=newSession().get(), str=i18n.str)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return index_tpl(str=i18n.str)
|
return index_tpl(str=i18n.str)
|
||||||
@@ -141,7 +142,7 @@ def post_user():
|
|||||||
|
|
||||||
def error(msg):
|
def error(msg):
|
||||||
return index_tpl(alerts=[('error', msg, 'fadeOut')], str=i18n.str)
|
return index_tpl(alerts=[('error', msg, 'fadeOut')], str=i18n.str)
|
||||||
|
|
||||||
if len(form('username')) < 3:
|
if len(form('username')) < 3:
|
||||||
return error(i18n.msg[2])
|
return error(i18n.msg[2])
|
||||||
elif not tools.input_validation(form('username')):
|
elif not tools.input_validation(form('username')):
|
||||||
@@ -155,11 +156,58 @@ def post_user():
|
|||||||
except Error as e:
|
except Error as e:
|
||||||
LOG.warning("Unsuccessful attempt to login %s: %s" % (form('username'), e))
|
LOG.warning("Unsuccessful attempt to login %s: %s" % (form('username'), e))
|
||||||
return error(str(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)
|
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')
|
@post('/signup')
|
||||||
def post_signup():
|
def post_signup():
|
||||||
@@ -183,7 +231,11 @@ def post_signup():
|
|||||||
def error(msg):
|
def error(msg):
|
||||||
return signup_tpl(alerts=[('error', msg, 'fadeOut')], str=i18n.str)
|
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]))
|
return(error(i18n.msg[6]))
|
||||||
|
|
||||||
if len(form('username')) < 3:
|
if len(form('username')) < 3:
|
||||||
@@ -210,7 +262,7 @@ def post_signup():
|
|||||||
return error(i18n.msg[15])
|
return error(i18n.msg[15])
|
||||||
|
|
||||||
if not tools.pwd_validation(form('password')):
|
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'):
|
elif form('password') != form('confirm-password'):
|
||||||
return error(i18n.msg[7])
|
return error(i18n.msg[7])
|
||||||
|
|
||||||
@@ -296,17 +348,16 @@ def post_enable_2fa():
|
|||||||
if(not newSession().get()['secureAuth']):
|
if(not newSession().get()['secureAuth']):
|
||||||
try:
|
try:
|
||||||
username=newSession().get()['username']
|
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:
|
except Error as e:
|
||||||
#add_auth_attribute_step1(newSession().get()['username'], None, None)
|
|
||||||
reload(newSession().get()['username'], None, None)
|
reload(newSession().get()['username'], None, None)
|
||||||
LOG.warning(e)
|
LOG.warning(e)
|
||||||
return error('2 urratseko autentifikazioa birgaitua izan da.')
|
return error(i18n.msg[30])
|
||||||
except Error as e:
|
except Error as e:
|
||||||
LOG.warning(e)
|
LOG.warning(e)
|
||||||
return index_tpl(alerts=[('error', e, 'fadeOut')], str=i18n.str)
|
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')
|
@post('/disable_2fa')
|
||||||
def post_disable_2fa():
|
def post_disable_2fa():
|
||||||
@@ -320,7 +371,6 @@ def post_disable_2fa():
|
|||||||
username=newSession().get()['username']
|
username=newSession().get()['username']
|
||||||
add_auth_attribute_step1(username, None, action='disable')
|
add_auth_attribute_step1(username, None, action='disable')
|
||||||
except Error as e:
|
except Error as e:
|
||||||
#add_auth_attribute_step1(newSession().get()['username'], None, None)
|
|
||||||
reload(newSession().get()['username'], None, None)
|
reload(newSession().get()['username'], None, None)
|
||||||
LOG.warning(e)
|
LOG.warning(e)
|
||||||
return error(str(e))
|
return error(str(e))
|
||||||
@@ -328,7 +378,7 @@ def post_disable_2fa():
|
|||||||
LOG.warning(e)
|
LOG.warning(e)
|
||||||
return index_tpl(alerts=[('error', e, 'fadeOut')], str=i18n.str)
|
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')
|
@post('/change_pwd')
|
||||||
def post_change_pwd():
|
def post_change_pwd():
|
||||||
@@ -388,11 +438,11 @@ def post_delete():
|
|||||||
def serve_static(filename):
|
def serve_static(filename):
|
||||||
return static_file(filename, root=path.join(BASE_DIR, 'static'))
|
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):
|
def font(filepath):
|
||||||
return static_file(filepath, root="static/fonts")
|
return static_file(filepath, root="static/fonts")
|
||||||
|
|
||||||
@get("/static/tmp/<filepath:re:.*\.(png|svg)>")
|
@get("/static/tmp/<filepath:re:.*\\.(png|svg)>")
|
||||||
def font(filepath):
|
def font(filepath):
|
||||||
return static_file(filepath, root="static/tmp")
|
return static_file(filepath, root="static/tmp")
|
||||||
|
|
||||||
@@ -431,8 +481,14 @@ def connect_ldap(conf, **kwargs):
|
|||||||
|
|
||||||
return Connection(server, raise_exceptions=True, **kwargs)
|
return Connection(server, raise_exceptions=True, **kwargs)
|
||||||
|
|
||||||
|
@error(404)
|
||||||
|
@error(405)
|
||||||
|
def error40x(error):
|
||||||
|
return index_tpl(str=i18n.str)
|
||||||
|
|
||||||
#LOGIN
|
#LOGIN
|
||||||
def login(username, password):
|
def login(username, password):
|
||||||
|
|
||||||
n = N
|
n = N
|
||||||
for key in (key for key in CONF.sections()
|
for key in (key for key in CONF.sections()
|
||||||
if key == 'ldap' or key.startswith('ldap:')):
|
if key == 'ldap' or key.startswith('ldap:')):
|
||||||
@@ -447,7 +503,6 @@ def login(username, password):
|
|||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
raise e
|
raise e
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
def login_user(conf, *args):
|
def login_user(conf, *args):
|
||||||
@@ -478,8 +533,11 @@ def login_user_ldap(conf, username, password):
|
|||||||
if is_trusted_device(conf, user_dn):
|
if is_trusted_device(conf, user_dn):
|
||||||
newSession().set(get_user_data(user_dn, c))
|
newSession().set(get_user_data(user_dn, c))
|
||||||
#update timestamp + ip address
|
#update timestamp + ip address
|
||||||
update_login_info(conf, user_dn)
|
update_login_info(conf, user_dn)
|
||||||
LOG.debug("%s logged in to %s" % (username, conf['base']))
|
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
|
#LOGOUT
|
||||||
def logout(username):
|
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,
|
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,
|
'devices':device, 'ip':request.environ.get('HTTP_X_REAL_IP', request.remote_addr), 'lastLogin': ts,
|
||||||
'secureAuth': False}
|
'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)
|
c.add(dn=new_user_dn,object_class=OBJECT_CLASS, attributes=attributes)
|
||||||
#create/change user password
|
#create/change user password
|
||||||
c.extend.standard.modify_password(new_user_dn, '', password)
|
c.extend.standard.modify_password(new_user_dn, '', password)
|
||||||
@@ -732,10 +791,10 @@ def add_auth_attribute_step1(username, code, action):
|
|||||||
try:
|
try:
|
||||||
add_auth_attribute_step2(CONF[key], username, code, action)
|
add_auth_attribute_step2(CONF[key], username, code, action)
|
||||||
changed.append(key)
|
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:
|
except Error as e:
|
||||||
for key in reversed(changed):
|
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:
|
try:
|
||||||
new_email_address(CONF[key], username, new_email, old_email)
|
new_email_address(CONF[key], username, new_email, old_email)
|
||||||
except Error as e2:
|
except Error as e2:
|
||||||
@@ -760,18 +819,16 @@ def add_auth_attribute_step2(conf, *args):
|
|||||||
|
|
||||||
except LDAPNoSuchAttributeResult as e:
|
except LDAPNoSuchAttributeResult as e:
|
||||||
LOG.error('{}: {!s}'.format(e.__class__.__name__, 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:
|
except LDAPExceptionError as e:
|
||||||
LOG.error('{}: {!s}'.format(e.__class__.__name__, e))
|
LOG.error('{}: {!s}'.format(e.__class__.__name__, e))
|
||||||
raise Error(i18n.msg[23])
|
raise Error(i18n.msg[23])
|
||||||
|
|
||||||
def add_auth_attribute_step3(conf, username, code, action):
|
def add_auth_attribute_step3(conf, username, code, action):
|
||||||
|
|
||||||
#set current LDAP
|
#set current LDAP
|
||||||
superUser = SuperUsers(conf)
|
superUser = SuperUsers(conf)
|
||||||
|
|
||||||
print(action)
|
|
||||||
with connect_ldap(conf, user=superUser.admin_dn, password=superUser.admin_pwd) as c:
|
with connect_ldap(conf, user=superUser.admin_dn, password=superUser.admin_pwd) as c:
|
||||||
user_dn = find_user_dn(conf, c, username)
|
user_dn = find_user_dn(conf, c, username)
|
||||||
if(action == 'enable'):
|
if(action == 'enable'):
|
||||||
@@ -952,6 +1009,12 @@ def get_user_email_array(user_dn, conn, old_email, new_email):
|
|||||||
emails[i] = new_email
|
emails[i] = new_email
|
||||||
return(emails)
|
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):
|
def get_user_data(user_dn, conn):
|
||||||
search_filter = '(objectClass=*)'
|
search_filter = '(objectClass=*)'
|
||||||
conn.search(user_dn, search_filter,
|
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].uid.values[0])
|
||||||
data.append(conn.entries[0].mail.values[0])
|
data.append(conn.entries[0].mail.values[0])
|
||||||
data.append(conn.entries[0].devices.values)
|
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 = conn.entries[0].lastLogin.values[0]
|
||||||
#ts = datetime.strptime(ts, '%Y-%m-%d %H:%M:%S%z')
|
#ts = datetime.strptime(ts, '%Y-%m-%d %H:%M:%S%z')
|
||||||
#ts = datetime.strftime(t, '%Y-%m-%d %H:%M:%S')
|
#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])
|
data.append(conn.entries[0].secureAuth.values[0])
|
||||||
if(conn.entries[0].authCode):
|
if(conn.entries[0].authCode):
|
||||||
data.append(conn.entries[0].authCode.values[0])
|
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):
|
if not find_device(user_dn, c, d):
|
||||||
OBJECT_CLASS = ['top', 'inetOrgPerson', 'posixAccount', 'accountsManagement']
|
OBJECT_CLASS = ['top', 'inetOrgPerson', 'posixAccount', 'accountsManagement']
|
||||||
c.modify(user_dn, {'devices': [( MODIFY_ADD, d )] })
|
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()
|
c.unbind()
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
LOG.warning(e)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def update_login_info(conf, user_dn):
|
def update_login_info(conf, user_dn):
|
||||||
@@ -1037,6 +1098,14 @@ def update_login_info(conf, user_dn):
|
|||||||
class Error(Exception):
|
class Error(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# TEMPORAL MEMORY
|
||||||
|
class tMemory(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.data = None
|
||||||
|
self.key = None
|
||||||
|
|
||||||
|
memo = tMemory()
|
||||||
|
|
||||||
#SESSIONS MANAGEMENT
|
#SESSIONS MANAGEMENT
|
||||||
def newSession():
|
def newSession():
|
||||||
|
|
||||||
@@ -1045,11 +1114,11 @@ def newSession():
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(Session, self).__init__()
|
super(Session, self).__init__()
|
||||||
self.data = bottle.request.environ.get('beaker.session')
|
self.data = bottle.request.environ.get('beaker.session')
|
||||||
self.lang = self.get_lang()
|
self.sid = self.data.id
|
||||||
#localization
|
#localization
|
||||||
self.lang = self.get_lang()
|
self.lang = self.get_lang()
|
||||||
global i18n
|
global i18n
|
||||||
i18n = LocalizeTo(self.lang, CONF)
|
i18n = LocalizeTo(self.lang, CONF)
|
||||||
|
|
||||||
def get_lang(self):
|
def get_lang(self):
|
||||||
if 'HTTP_ACCEPT_LANGUAGE' in bottle.request.environ:
|
if 'HTTP_ACCEPT_LANGUAGE' in bottle.request.environ:
|
||||||
@@ -1092,6 +1161,8 @@ def newSession():
|
|||||||
self.data['secureAuth'] = self.secureAuth
|
self.data['secureAuth'] = self.secureAuth
|
||||||
self.data['authCode'] = self.authCode
|
self.data['authCode'] = self.authCode
|
||||||
|
|
||||||
|
self.data['id'] = self.sid
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
self.data.pop('username')
|
self.data.pop('username')
|
||||||
|
|
||||||
@@ -1128,7 +1199,8 @@ class SuperUsers(object):
|
|||||||
|
|
||||||
superUser = SuperUsers(CONF['ldap:0'])
|
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]
|
bottle.TEMPLATE_PATH = [BASE_DIR]
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -14,13 +14,22 @@
|
|||||||
<body>
|
<body>
|
||||||
<main>
|
<main>
|
||||||
<h1>{{ str['login'] }}</h1>
|
<h1>{{ str['login'] }}</h1>
|
||||||
|
|
||||||
|
%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>
|
||||||
|
|
||||||
<form method="post" action="/user">
|
<label for="password">{{ str['pwd'] }}</label>
|
||||||
<label for="username">{{ str['usrn'] }}</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>
|
||||||
<input id="username" name="username" value="{{ get('username', '') }}" type="text" required autofocus>
|
|
||||||
|
%end
|
||||||
<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>
|
|
||||||
|
|
||||||
<button class="green" type="submit">{{str['login']}}</button>
|
<button class="green" type="submit">{{str['login']}}</button>
|
||||||
<a href="/signup">{{ str['or-sign-up'] }}</a>
|
<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 onetimepass import valid_totp
|
||||||
from secrets import choice
|
from secrets import choice
|
||||||
import segno
|
import segno
|
||||||
|
from os import path
|
||||||
|
import uuid
|
||||||
|
|
||||||
class Tools():
|
class Tools():
|
||||||
|
|
||||||
@@ -47,12 +49,28 @@ class Tools():
|
|||||||
return(bool(re.fullmatch(regex, e)))
|
return(bool(re.fullmatch(regex, e)))
|
||||||
|
|
||||||
# 2FA
|
# 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 = ''
|
secret = ''
|
||||||
while len(secret) < 16:
|
while len(secret) < 16:
|
||||||
secret += choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567')
|
secret += choice('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567')
|
||||||
qrcode = segno.make(secret, micro=False)
|
self.gen_qr(secret)
|
||||||
qrcode.save('static/tmp/'+secret+'.png', scale=10)
|
|
||||||
return 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()
|
tools = Tools()
|
||||||
|
|||||||
+17
-2
@@ -40,6 +40,13 @@ class LocalizeTo(object):
|
|||||||
str_25 = _("Last login")
|
str_25 = _("Last login")
|
||||||
str_26 = _("Devices")
|
str_26 = _("Devices")
|
||||||
str_27 = _("show")
|
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
|
#messages
|
||||||
msg_00 = _("The session was closed.")
|
msg_00 = _("The session was closed.")
|
||||||
@@ -71,11 +78,19 @@ class LocalizeTo(object):
|
|||||||
msg_26 = _("Forgot your password? Please try again.")
|
msg_26 = _("Forgot your password? Please try again.")
|
||||||
msg_27 = _("The session has expired.")
|
msg_27 = _("The session has expired.")
|
||||||
msg_28 = _("Registration is currently closed. We apologize for the inconvenience.")
|
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,
|
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,
|
'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,
|
'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,
|
'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,
|
'del-account':str_22, 'welcome':str_23, 'logs':str_24, 'last-login':str_25, 'devices':str_26,
|
||||||
'show':str_27, 'pwd-pattern': msg_08}
|
'show':str_27, '2fa-title':str_28, 'token':str_29, 'disable':str_30, 'enable':str_31, '2fa-info-1':str_32,
|
||||||
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)
|
'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
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: 0.0.3\n"
|
||||||
"Report-Msgid-Bugs-To: \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"
|
"PO-Revision-Date: 2023-04-07 13:28+0200\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
"Language: \n"
|
|
||||||
"MIME-Version: 1.0\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"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
"X-Generator: Poedit 3.2.2\n"
|
||||||
|
|
||||||
#: libs/localization.py:15
|
#: libs/localization.py:15
|
||||||
msgid "User"
|
msgid "User"
|
||||||
msgstr "User"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:16
|
#: libs/localization.py:16
|
||||||
msgid "Username"
|
msgid "Username"
|
||||||
msgstr "Username"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:17
|
#: libs/localization.py:17
|
||||||
msgid "Firstname"
|
msgid "Firstname"
|
||||||
msgstr "Firstname"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:18
|
#: libs/localization.py:18
|
||||||
msgid "Surname"
|
msgid "Surname"
|
||||||
msgstr "Surname"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:19
|
#: libs/localization.py:19
|
||||||
msgid "Password"
|
msgid "Password"
|
||||||
msgstr "Password"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:20
|
#: libs/localization.py:20
|
||||||
msgid "Old password"
|
msgid "Old password"
|
||||||
msgstr "Old password"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:21
|
#: libs/localization.py:21
|
||||||
msgid "New password"
|
msgid "New password"
|
||||||
msgstr "New password"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:22
|
#: libs/localization.py:22
|
||||||
msgid "Confirm password"
|
msgid "Confirm password"
|
||||||
msgstr "Confirm password"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:23
|
#: libs/localization.py:23
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
msgstr "Email"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:24
|
#: libs/localization.py:24
|
||||||
msgid "edit"
|
msgid "edit"
|
||||||
msgstr "edit"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:25
|
#: libs/localization.py:25
|
||||||
msgid "Login"
|
msgid "Login"
|
||||||
msgstr "Login"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:26
|
#: libs/localization.py:26
|
||||||
msgid "Logout"
|
msgid "Logout"
|
||||||
msgstr "Logout"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:27
|
#: libs/localization.py:27
|
||||||
msgid "Delete"
|
msgid "Delete"
|
||||||
msgstr "Delete"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:28
|
#: libs/localization.py:28
|
||||||
msgid "Sign Up"
|
msgid "Sign Up"
|
||||||
msgstr "Sign Up"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:29
|
#: libs/localization.py:29
|
||||||
msgid "Back"
|
msgid "Back"
|
||||||
msgstr "Back"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:30
|
#: libs/localization.py:30
|
||||||
msgid "Update"
|
msgid "Update"
|
||||||
msgstr "Update"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:31
|
#: libs/localization.py:31
|
||||||
msgid "Or Sign In"
|
msgid "Or Sign In"
|
||||||
msgstr "Or Sign In"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:32
|
#: libs/localization.py:32
|
||||||
msgid "Or Sign Up"
|
msgid "Or Sign Up"
|
||||||
msgstr "Or Sign Up"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:33
|
#: libs/localization.py:33
|
||||||
msgid "Invite code"
|
msgid "Invite code"
|
||||||
msgstr "Invite code"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:34
|
#: libs/localization.py:34
|
||||||
msgid "Edit your fullname"
|
msgid "Edit your fullname"
|
||||||
msgstr "Edit your fullname"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:35
|
#: libs/localization.py:35
|
||||||
msgid "Edit your email"
|
msgid "Edit your email"
|
||||||
msgstr "Edit your email"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:36
|
#: libs/localization.py:36
|
||||||
msgid "Change your password"
|
msgid "Change your password"
|
||||||
msgstr "Change your password"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:37
|
#: libs/localization.py:37
|
||||||
msgid "Delete your account"
|
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"
|
msgid "Welcome"
|
||||||
msgstr "Welcome"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:39
|
#: libs/localization.py:39
|
||||||
msgid "Logs"
|
msgid "Logs"
|
||||||
msgstr "Logs"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:40
|
#: libs/localization.py:40
|
||||||
msgid "Last login"
|
msgid "Last login"
|
||||||
msgstr "Last login"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:41
|
#: libs/localization.py:41
|
||||||
msgid "Devices"
|
msgid "Devices"
|
||||||
msgstr "Devices"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:42
|
#: libs/localization.py:42
|
||||||
msgid "show"
|
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
|
#: libs/localization.py:45
|
||||||
msgid "The session was closed."
|
msgid "Disable"
|
||||||
msgstr "The session was closed."
|
msgstr ""
|
||||||
|
|
||||||
|
#: libs/localization.py:46
|
||||||
|
msgid "Enable"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:47
|
#: libs/localization.py:47
|
||||||
msgid "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 "Username must be at least 3 characters long!"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:48
|
#: libs/localization.py:48
|
||||||
msgid "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 "Not allowed characters for the username field."
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:49
|
#: libs/localization.py:49
|
||||||
msgid "Not allowed characters for the firstname field."
|
msgid "Code"
|
||||||
msgstr "Not allowed characters for the firstname field."
|
msgstr ""
|
||||||
|
|
||||||
#: 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."
|
|
||||||
|
|
||||||
#: libs/localization.py:52
|
#: libs/localization.py:52
|
||||||
msgid "Passwords do not match!"
|
msgid "The session was closed."
|
||||||
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 ""
|
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:54
|
||||||
msgid "Congratulations, your account has been created!"
|
msgid "Username must be at least 3 characters long!"
|
||||||
msgstr "Congratulations, your account has been created!"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:55
|
#: libs/localization.py:55
|
||||||
msgid "Your first and last name have not been changed."
|
msgid "Not allowed characters for the username field."
|
||||||
msgstr "Your first and last name have not been changed."
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:56
|
#: libs/localization.py:56
|
||||||
msgid "Your firstname is a bit short, don't you think?"
|
msgid "Not allowed characters for the firstname field."
|
||||||
msgstr "Your firstname is a bit short, don't you think?"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:57
|
#: libs/localization.py:57
|
||||||
msgid "Your surname is a bit short, don't you think?"
|
msgid "Not allowed characters for the surname field."
|
||||||
msgstr "Your surname is a bit short, don't you think?"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:58
|
#: libs/localization.py:58
|
||||||
msgid "Your first and last name have been successfully updated."
|
msgid "The code is invalid or has expired."
|
||||||
msgstr "Your first and last name have been successfully updated."
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:59
|
#: libs/localization.py:59
|
||||||
msgid "Invalid email address. Please try again."
|
msgid "Passwords do not match!"
|
||||||
msgstr "Invalid email address. Please try again."
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:60
|
#: libs/localization.py:60
|
||||||
msgid "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 "Email address has not been changed."
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:61
|
#: libs/localization.py:61
|
||||||
msgid "Your email has been successfully updated."
|
msgid "Congratulations, your account has been created!"
|
||||||
msgstr "Your email has been successfully updated."
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:62
|
#: libs/localization.py:62
|
||||||
msgid "The password entered is the same as the current password."
|
msgid "Your first and last name have not been changed."
|
||||||
msgstr "The password entered is the same as the current password."
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:63
|
#: libs/localization.py:63
|
||||||
msgid "Password has been changed!"
|
msgid "Your firstname is a bit short, don't you think?"
|
||||||
msgstr "Password has been changed!"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:64
|
#: libs/localization.py:64
|
||||||
msgid "Please, type your username for account deletion."
|
msgid "Your surname is a bit short, don't you think?"
|
||||||
msgstr "Please, type your username for account deletion."
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:65
|
#: libs/localization.py:65
|
||||||
msgid "Account successfully deleted!"
|
msgid "Your first and last name have been successfully updated."
|
||||||
msgstr "Account successfully deleted!"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:66
|
#: libs/localization.py:66
|
||||||
msgid "Username or password is incorrect!"
|
msgid "Invalid email address. Please try again."
|
||||||
msgstr "Username or password is incorrect!"
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:67
|
#: libs/localization.py:67
|
||||||
msgid "Unable to connect to the remote server."
|
msgid "Email address has not been changed."
|
||||||
msgstr "Unable to connect to the remote server."
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:68
|
#: libs/localization.py:68
|
||||||
msgid ""
|
msgid "Your email has been successfully updated."
|
||||||
"Encountered an unexpected error while communicating with the remote server."
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Encountered an unexpected error while communicating with the remote server."
|
|
||||||
|
|
||||||
#: libs/localization.py:69
|
#: libs/localization.py:69
|
||||||
msgid "User already exists."
|
msgid "The password entered is the same as the current password."
|
||||||
msgstr "User already exists."
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:70
|
#: libs/localization.py:70
|
||||||
msgid "Email already exists."
|
msgid "Password has been changed!"
|
||||||
msgstr "Email already exists."
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:71
|
#: libs/localization.py:71
|
||||||
msgid "Forgot your password? Please try again."
|
msgid "Please, type your username for account deletion."
|
||||||
msgstr "Forgot your password? Please try again."
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:72
|
#: libs/localization.py:72
|
||||||
msgid "The session has expired."
|
msgid "Account successfully deleted!"
|
||||||
msgstr "The session has expired."
|
msgstr ""
|
||||||
|
|
||||||
#: libs/localization.py:73
|
#: 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."
|
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.
|
# SOME DESCRIPTIVE TITLE.
|
||||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
# This file is distributed under the same license as the PACKAGE package.
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
# FIRST AUTHOR <aitzol@lainoa.eus>, 2022.
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: 0.0.1\n"
|
"Project-Id-Version: 0.0.3\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-04-07 17:20+0200\n"
|
"POT-Creation-Date: 2022-04-25 16:52+0200\n"
|
||||||
"PO-Revision-Date: 2023-04-07 13:28+0200\n"
|
"PO-Revision-Date: 2023-11-27 15:37+0100\n"
|
||||||
"Last-Translator: Aitzol Berasategi <aitzol@lainoa.eus>\n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: LANGUAGE <EN@en.org>\n"
|
"Language-Team: \n"
|
||||||
"Language: en\n"
|
"Language: en\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Generator: Poedit 2.3\n"
|
"X-Generator: Poedit 3.2.2\n"
|
||||||
|
|
||||||
#: libs/localization.py:15
|
#: libs/localization.py:15
|
||||||
msgid "User"
|
msgid "User"
|
||||||
@@ -109,7 +109,7 @@ msgstr "Change your password"
|
|||||||
msgid "Delete your account"
|
msgid "Delete your account"
|
||||||
msgstr "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"
|
msgid "Welcome"
|
||||||
msgstr "Welcome"
|
msgstr "Welcome"
|
||||||
|
|
||||||
@@ -129,120 +129,162 @@ msgstr "Devices"
|
|||||||
msgid "show"
|
msgid "show"
|
||||||
msgstr "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
|
#: 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."
|
msgid "The session was closed."
|
||||||
msgstr "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!"
|
msgid "Username must be at least 3 characters long!"
|
||||||
msgstr "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."
|
msgid "Not allowed characters for the username field."
|
||||||
msgstr "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."
|
msgid "Not allowed characters for the firstname field."
|
||||||
msgstr "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."
|
msgid "Not allowed characters for the surname field."
|
||||||
msgstr "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."
|
msgid "The code is invalid or has expired."
|
||||||
msgstr "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!"
|
msgid "Passwords do not match!"
|
||||||
msgstr "Passwords do not match!"
|
msgstr "Passwords do not match!"
|
||||||
|
|
||||||
#: libs/localization.py:53
|
#: libs/localization.py:60
|
||||||
msgid ""
|
msgid "The password must contain at least 8 characters, at least one number, a capital letter and a special character."
|
||||||
"The password must contain at least 8 characters, at least one number, "
|
msgstr "The password must contain at least 8 characters, at least one number, a capital letter and a special character."
|
||||||
"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!"
|
msgid "Congratulations, your account has been created!"
|
||||||
msgstr "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."
|
msgid "Your first and last name have not been changed."
|
||||||
msgstr "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?"
|
msgid "Your firstname is a bit short, don't you think?"
|
||||||
msgstr "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?"
|
msgid "Your surname is a bit short, don't you think?"
|
||||||
msgstr "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."
|
msgid "Your first and last name have been successfully updated."
|
||||||
msgstr "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."
|
msgid "Invalid email address. Please try again."
|
||||||
msgstr "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."
|
msgid "Email address has not been changed."
|
||||||
msgstr "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."
|
msgid "Your email has been successfully updated."
|
||||||
msgstr "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."
|
msgid "The password entered is the same as the current password."
|
||||||
msgstr "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!"
|
msgid "Password has been changed!"
|
||||||
msgstr "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."
|
msgid "Please, type your username for account deletion."
|
||||||
msgstr "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!"
|
msgid "Account successfully deleted!"
|
||||||
msgstr "Account successfully deleted!"
|
msgstr "Account successfully deleted!"
|
||||||
|
|
||||||
#: libs/localization.py:66
|
#: libs/localization.py:73
|
||||||
msgid "Username or password is incorrect!"
|
msgid "Username or password is incorrect!"
|
||||||
msgstr "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."
|
msgid "Unable to connect to the remote server."
|
||||||
msgstr "Unable to connect to the remote server."
|
msgstr "Unable to connect to the remote server."
|
||||||
|
|
||||||
#: libs/localization.py:68
|
#: libs/localization.py:75
|
||||||
msgid ""
|
msgid "Encountered an unexpected error while communicating with the remote server."
|
||||||
"Encountered an unexpected error while communicating with the remote server."
|
msgstr "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."
|
msgid "User already exists."
|
||||||
msgstr "User already exists."
|
msgstr "User already exists."
|
||||||
|
|
||||||
#: libs/localization.py:70
|
#: libs/localization.py:77
|
||||||
msgid "Email already exists."
|
msgid "Email already exists."
|
||||||
msgstr "Email already exists."
|
msgstr "Email already exists."
|
||||||
|
|
||||||
#: libs/localization.py:71
|
#: libs/localization.py:78
|
||||||
msgid "Forgot your password? Please try again."
|
msgid "Forgot your password? Please try again."
|
||||||
msgstr "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."
|
msgid "The session has expired."
|
||||||
msgstr "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."
|
msgid "Registration is currently closed. We apologize for the inconvenience."
|
||||||
msgstr "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 ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: 0.0.1\n"
|
"Project-Id-Version: 0.0.3\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2022-04-07 17:23+0200\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"
|
"Last-Translator: Aitzol Berasategi <aitzol@lainoa.eus>\n"
|
||||||
"Language-Team: LANGUAGE <EU@eu.org>\n"
|
"Language-Team: LANGUAGE <EU@eu.org>\n"
|
||||||
"Language: eu\n"
|
"Language: eu\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Generator: Poedit 2.3\n"
|
"X-Generator: Poedit 3.2.2\n"
|
||||||
|
|
||||||
#: libs/localization.py:15
|
#: libs/localization.py:15
|
||||||
msgid "User"
|
msgid "User"
|
||||||
@@ -109,7 +109,7 @@ msgstr "Pasahitza eguneratu"
|
|||||||
msgid "Delete your account"
|
msgid "Delete your account"
|
||||||
msgstr "Kontua ezabatu"
|
msgstr "Kontua ezabatu"
|
||||||
|
|
||||||
#: libs/localization.py:38 libs/localization.py:46
|
#: libs/localization.py:38 libs/localization.py:53
|
||||||
msgid "Welcome"
|
msgid "Welcome"
|
||||||
msgstr "Ongi etorri"
|
msgstr "Ongi etorri"
|
||||||
|
|
||||||
@@ -129,119 +129,162 @@ msgstr "Gailuak"
|
|||||||
msgid "show"
|
msgid "show"
|
||||||
msgstr "ikusi"
|
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
|
#: 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."
|
msgid "The session was closed."
|
||||||
msgstr "Saioa itxi da."
|
msgstr "Saioa itxi da."
|
||||||
|
|
||||||
#: libs/localization.py:47
|
#: libs/localization.py:54
|
||||||
msgid "Username must be at least 3 characters long!"
|
msgid "Username must be at least 3 characters long!"
|
||||||
msgstr "Erabiltzaile izenak gutxienez 3 karaktere izan behar ditu!"
|
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."
|
msgid "Not allowed characters for the username field."
|
||||||
msgstr "Erabiltzaile-izenaren eremurako onartzen ez diren karaktereak."
|
msgstr "Erabiltzaile-izenaren eremurako onartzen ez diren karaktereak."
|
||||||
|
|
||||||
#: libs/localization.py:49
|
#: libs/localization.py:56
|
||||||
msgid "Not allowed characters for the firstname field."
|
msgid "Not allowed characters for the firstname field."
|
||||||
msgstr "Izenaren eremurako onartzen ez diren karaktereak."
|
msgstr "Izenaren eremurako onartzen ez diren karaktereak."
|
||||||
|
|
||||||
#: libs/localization.py:50
|
#: libs/localization.py:57
|
||||||
msgid "Not allowed characters for the surname field."
|
msgid "Not allowed characters for the surname field."
|
||||||
msgstr "Abizenaren eremurako onartzen ez diren karaktereak."
|
msgstr "Abizenaren eremurako onartzen ez diren karaktereak."
|
||||||
|
|
||||||
#: libs/localization.py:51
|
#: libs/localization.py:58
|
||||||
msgid "The code is invalid or has expired."
|
msgid "The code is invalid or has expired."
|
||||||
msgstr "Kodea baliogabea da edo iraungi egin da."
|
msgstr "Kodea baliogabea da edo iraungi egin da."
|
||||||
|
|
||||||
#: libs/localization.py:52
|
#: libs/localization.py:59
|
||||||
msgid "Passwords do not match!"
|
msgid "Passwords do not match!"
|
||||||
msgstr "Pasahitzak ez datoz bat!"
|
msgstr "Pasahitzak ez datoz bat!"
|
||||||
|
|
||||||
#: libs/localization.py:53
|
#: libs/localization.py:60
|
||||||
msgid ""
|
msgid "The password must contain at least 8 characters, at least one number, a capital letter and a special character."
|
||||||
"The password must contain at least 8 characters, at least one number, "
|
msgstr "Pasahitzak gutxienez 8 karaktere izan behar ditu, zenbaki bat, hizki larri bat eta karaktere berezi bat."
|
||||||
"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!"
|
msgid "Congratulations, your account has been created!"
|
||||||
msgstr "Zorionak, zure kontua sortu da!"
|
msgstr "Zorionak, zure kontua sortu da!"
|
||||||
|
|
||||||
#: libs/localization.py:55
|
#: libs/localization.py:62
|
||||||
msgid "Your first and last name have not been changed."
|
msgid "Your first and last name have not been changed."
|
||||||
msgstr "Zure izen-abizenak ez dira aldatu."
|
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?"
|
msgid "Your firstname is a bit short, don't you think?"
|
||||||
msgstr "Zure izena labur-xamarra da, ez duzu uste?"
|
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?"
|
msgid "Your surname is a bit short, don't you think?"
|
||||||
msgstr "Zure abizena labur-xamarra da, ez duzu uste?"
|
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."
|
msgid "Your first and last name have been successfully updated."
|
||||||
msgstr "Zure izen-abizenak ongi eguneratu dira."
|
msgstr "Zure izen-abizenak ongi eguneratu dira."
|
||||||
|
|
||||||
#: libs/localization.py:59
|
#: libs/localization.py:66
|
||||||
msgid "Invalid email address. Please try again."
|
msgid "Invalid email address. Please try again."
|
||||||
msgstr "Baliogabeko email helbidea. Saia zaitez berriz, mesedez."
|
msgstr "Baliogabeko email helbidea. Saia zaitez berriz, mesedez."
|
||||||
|
|
||||||
#: libs/localization.py:60
|
#: libs/localization.py:67
|
||||||
msgid "Email address has not been changed."
|
msgid "Email address has not been changed."
|
||||||
msgstr "Email helbidea ez da aldatu."
|
msgstr "Email helbidea ez da aldatu."
|
||||||
|
|
||||||
#: libs/localization.py:61
|
#: libs/localization.py:68
|
||||||
msgid "Your email has been successfully updated."
|
msgid "Your email has been successfully updated."
|
||||||
msgstr "Zure emaila ongi eguneratu da."
|
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."
|
msgid "The password entered is the same as the current password."
|
||||||
msgstr "Sartutako pasahitza egungo pasahitzaren berdina da."
|
msgstr "Sartutako pasahitza egungo pasahitzaren berdina da."
|
||||||
|
|
||||||
#: libs/localization.py:63
|
#: libs/localization.py:70
|
||||||
msgid "Password has been changed!"
|
msgid "Password has been changed!"
|
||||||
msgstr "Pasahitza eguneratua izan da!"
|
msgstr "Pasahitza eguneratua izan da!"
|
||||||
|
|
||||||
#: libs/localization.py:64
|
#: libs/localization.py:71
|
||||||
msgid "Please, type your username for account deletion."
|
msgid "Please, type your username for account deletion."
|
||||||
msgstr "Kontua ezabatzeko idatzi zure erabiltzaile izena, mesedez."
|
msgstr "Kontua ezabatzeko idatzi zure erabiltzaile izena, mesedez."
|
||||||
|
|
||||||
#: libs/localization.py:65
|
#: libs/localization.py:72
|
||||||
msgid "Account successfully deleted!"
|
msgid "Account successfully deleted!"
|
||||||
msgstr "Kontua ongi ezabatu da!"
|
msgstr "Kontua ongi ezabatu da!"
|
||||||
|
|
||||||
#: libs/localization.py:66
|
#: libs/localization.py:73
|
||||||
msgid "Username or password is incorrect!"
|
msgid "Username or password is incorrect!"
|
||||||
msgstr "Erabiltzaile izena edo pasahitza okerrak dira!"
|
msgstr "Erabiltzaile izena edo pasahitza okerrak dira!"
|
||||||
|
|
||||||
#: libs/localization.py:67
|
#: libs/localization.py:74
|
||||||
msgid "Unable to connect to the remote server."
|
msgid "Unable to connect to the remote server."
|
||||||
msgstr "Ezinezkoa urruneko zerbitzara konektatzea."
|
msgstr "Ezinezkoa urruneko zerbitzara konektatzea."
|
||||||
|
|
||||||
#: libs/localization.py:68
|
#: libs/localization.py:75
|
||||||
msgid ""
|
msgid "Encountered an unexpected error while communicating with the remote server."
|
||||||
"Encountered an unexpected error while communicating with the remote server."
|
|
||||||
msgstr "Ezusteko errore bat gertatu da urruneko zerbitzariarekin komunikatzean."
|
msgstr "Ezusteko errore bat gertatu da urruneko zerbitzariarekin komunikatzean."
|
||||||
|
|
||||||
#: libs/localization.py:69
|
#: libs/localization.py:76
|
||||||
msgid "User already exists."
|
msgid "User already exists."
|
||||||
msgstr "Erabiltzaile hori existitzen da."
|
msgstr "Erabiltzaile hori existitzen da."
|
||||||
|
|
||||||
#: libs/localization.py:70
|
#: libs/localization.py:77
|
||||||
msgid "Email already exists."
|
msgid "Email already exists."
|
||||||
msgstr "Email hori existitzen da."
|
msgstr "Email hori existitzen da."
|
||||||
|
|
||||||
#: libs/localization.py:71
|
#: libs/localization.py:78
|
||||||
msgid "Forgot your password? Please try again."
|
msgid "Forgot your password? Please try again."
|
||||||
msgstr "Zure pasahitza ahaztu duzu? Saia zeitez berriz, mesedez."
|
msgstr "Zure pasahitza ahaztu duzu? Saia zeitez berriz, mesedez."
|
||||||
|
|
||||||
#: libs/localization.py:72
|
#: libs/localization.py:79
|
||||||
msgid "The session has expired."
|
msgid "The session has expired."
|
||||||
msgstr "Saioa iraungi egin da."
|
msgstr "Saioa iraungi egin da."
|
||||||
|
|
||||||
#: libs/localization.py:73
|
#: libs/localization.py:80
|
||||||
msgid "Registration is currently closed. We apologize for the inconvenience."
|
msgid "Registration is currently closed. We apologize for the inconvenience."
|
||||||
msgstr "Izen-ematea itxita dago une honetan. Barkatu eragozpenak."
|
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>=0.12.19
|
||||||
bottle-beaker>=0.1.3
|
bottle-beaker>=0.1.3
|
||||||
ldap3>=2.9.1
|
ldap3>=2.9.1
|
||||||
@@ -5,3 +6,6 @@ uwsgi>=2.0.21
|
|||||||
pyyaml>=6.0
|
pyyaml>=6.0
|
||||||
ua-parser>=0.16.1
|
ua-parser>=0.16.1
|
||||||
user-agents>=2.2.0
|
user-agents>=2.2.0
|
||||||
|
cryptocode==0.1
|
||||||
|
onetimepass==1.0.1
|
||||||
|
segno==1.5.3
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
##############################
|
#!/bin/bash
|
||||||
|
##############################
|
||||||
## Erabilera: ##
|
## Erabilera: ##
|
||||||
## sudo chmod +x start.sh ##
|
## sudo chmod +x start.sh ##
|
||||||
## ./start.sh $UID ##
|
## ./start.sh $UID ##
|
||||||
##############################
|
##############################
|
||||||
#!/bin/bash
|
|
||||||
if [ ! -f settings.ini ]; then
|
if [ ! -f settings.ini ]; then
|
||||||
cp settings.ini.example settings.ini
|
cp settings.ini.example settings.ini
|
||||||
fi
|
fi
|
||||||
@@ -11,8 +11,11 @@ fi
|
|||||||
if [[ $# -gt 0 ]]; then
|
if [[ $# -gt 0 ]]; then
|
||||||
UID_=$1
|
UID_=$1
|
||||||
echo $UID_
|
echo $UID_
|
||||||
export LDAP_ADMIN_PASSWORD=admin
|
else
|
||||||
export LDAP_READONLY_PASSWORD=readonly
|
UID_=$UID
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
export LDAP_ADMIN_PASSWORD=admin
|
||||||
|
export LDAP_READONLY_PASSWORD=readonly
|
||||||
|
|
||||||
uwsgi --http :9090 --enable-threads --uid $UID_ --wsgi-file app.py
|
uwsgi --http :9090 --enable-threads --uid $UID_ --wsgi-file app.py
|
||||||
|
|||||||
@@ -201,6 +201,15 @@ button.red:hover{
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**/
|
||||||
|
|
||||||
|
.info {
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 24rem;
|
||||||
|
padding: 0 2.5rem 0 2.5rem;
|
||||||
|
text-align: justify;
|
||||||
|
}
|
||||||
|
|
||||||
/**/
|
/**/
|
||||||
.grid-container {
|
.grid-container {
|
||||||
display: grid;
|
display: grid;
|
||||||
@@ -233,7 +242,16 @@ button.red:hover{
|
|||||||
form {
|
form {
|
||||||
border: 0;
|
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="grid-item">
|
||||||
<div class="account">
|
<div class="account">
|
||||||
<h5>2FA</h5>
|
<h5>2FA</h5>
|
||||||
<p>Bi urratseko autentifikazioa</p>
|
<p>{{ str['2fa-title'] }}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -4,5 +4,6 @@
|
|||||||
http = :8080
|
http = :8080
|
||||||
chdir = %v
|
chdir = %v
|
||||||
wsgi-file = %v/app.py
|
wsgi-file = %v/app.py
|
||||||
|
enable-thread = true
|
||||||
processes = 1
|
processes = 1
|
||||||
threads = 2
|
threads = 2
|
||||||
|
|||||||
Reference in New Issue
Block a user