用户登录相关功能实现完毕:密码登录、身份验证器动态密码登录,支持为单独用户指定登录认证方式,也可以使用系统默认设置。

pull/105/head
Apex Liu 2017-11-19 13:37:57 +08:00
parent 980a684d85
commit 6cd8d29470
20 changed files with 261 additions and 201 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
#用户账号示例文件使用CSV格式每行一个用户用英文逗号分隔9个字段需要8个英文逗号,,,,,,,,
#用户账号,用户姓名,登录认证方式,EMail,Mobile,QQ,微信,所属组,描述
zhangsan,张三,1,zhangsan@domain.tld,,12345678,112233,运维人员|审计员,
lisi,李四,1,lisi@domain.tld,,,,审计员,
wangwu,王五,1,wangwu@domain.tld,,,,,
bai.lee,李白,1,bai.lee@domain.tld,,10086,bai.lee,审计管理员,著名诗人、剑客
#用户账号示例文件使用CSV格式每行一个用户用英文逗号分隔8个字段需要7个英文逗号,,,,,,,
#用户账号,用户姓名,EMail,Mobile,QQ,微信,所属组,描述
zhangsan,张三,zhangsan@domain.tld,,12345678,112233,运维人员|审计员,
lisi,李四,lisi@domain.tld,,,,审计员,
wangwu,,,,,,,
bai.lee,李白,bai.lee@domain.tld,,10086,bai.lee,审计管理员,著名诗人

1 #用户账号示例文件,使用CSV格式,每行一个用户,用英文逗号分隔,共9个字段,需要8个英文逗号 #用户账号示例文件,使用CSV格式,每行一个用户,用英文逗号分隔,共8个字段,需要7个英文逗号
2 #用户账号 #用户账号 用户姓名 登录认证方式 EMail EMail Mobile Mobile QQ QQ 微信 微信 所属组 所属组 描述 描述
3 zhangsan zhangsan 张三 1 zhangsan@domain.tld zhangsan@domain.tld 12345678 12345678 112233 112233 运维人员|审计员 运维人员|审计员
4 lisi lisi 李四 1 lisi@domain.tld lisi@domain.tld 审计员 审计员
5 wangwu wangwu 王五 1 wangwu@domain.tld
6 bai.lee bai.lee 李白 1 bai.lee@domain.tld bai.lee@domain.tld 10086 10086 bai.lee bai.lee 审计管理员 审计管理员 著名诗人 著名诗人、剑客

View File

@ -198,7 +198,7 @@ $app.do_account_login = function (username, password, captcha, oath, is_remember
window.location.href = $app.options.ref;
} else {
$app.hide_op_box();
$app.show_op_box('error', '无法登录TELEPORT' + tp_error_msg(ret.code, ret.message));
$app.show_op_box('error', '登录失败' + tp_error_msg(ret.code, ret.message));
console.log(ret);
}

View File

@ -312,9 +312,9 @@ $app.create_config_sec = function () {
input_session_timeout: $('#sec-session-timeout'),
input_login_retry: $('#sec-login-retry'),
input_lock_timeout: $('#sec-lock-timeout'),
btn_auth_username_password: $('#sec-auth-username-password'),
// btn_auth_username_password: $('#sec-auth-username-password'),
btn_auth_username_password_captcha: $('#sec-auth-username-password-captcha'),
btn_auth_username_oath: $('#sec-auth-username-oath'),
// btn_auth_username_oath: $('#sec-auth-username-oath'),
btn_auth_username_password_oath: $('#sec-auth-username-password-oath')
};
@ -353,13 +353,16 @@ $app.create_config_sec = function () {
_sec.dom.input_login_retry.val(login.retry);
_sec.dom.input_lock_timeout.val(login.lock_timeout);
_sec.dom.btn_auth_username_password.removeClass('tp-selected');
if (login.auth & TP_LOGIN_AUTH_USERNAME_PASSWORD)
_sec.dom.btn_auth_username_password.addClass('tp-selected');
// _sec.dom.btn_auth_username_password.removeClass('tp-selected');
// if (login.auth & TP_LOGIN_AUTH_USERNAME_PASSWORD)
// _sec.dom.btn_auth_username_password.addClass('tp-selected');
_sec.dom.btn_auth_username_password_captcha.removeClass('tp-selected');
if (login.auth & TP_LOGIN_AUTH_USERNAME_PASSWORD_CAPTCHA)
_sec.dom.btn_auth_username_password_captcha.addClass('tp-selected');
if (login.auth & TP_LOGIN_AUTH_USERNAME_OATH)
_sec.dom.btn_auth_username_oath.addClass('tp-selected');
// _sec.dom.btn_auth_username_oath.removeClass('tp-selected');
// if (login.auth & TP_LOGIN_AUTH_USERNAME_OATH)
// _sec.dom.btn_auth_username_oath.addClass('tp-selected');
_sec.dom.btn_auth_username_password_oath.removeClass('tp-selected');
if (login.auth & TP_LOGIN_AUTH_USERNAME_PASSWORD_OATH)
_sec.dom.btn_auth_username_password_oath.addClass('tp-selected');
};
@ -374,12 +377,12 @@ $app.create_config_sec = function () {
var _login_lock_timeout = parseInt(_sec.dom.input_lock_timeout.val());
var _login_auth = 0;
if (_sec.dom.btn_auth_username_password.hasClass('tp-selected'))
_login_auth |= TP_LOGIN_AUTH_USERNAME_PASSWORD;
// if (_sec.dom.btn_auth_username_password.hasClass('tp-selected'))
// _login_auth |= TP_LOGIN_AUTH_USERNAME_PASSWORD;
if (_sec.dom.btn_auth_username_password_captcha.hasClass('tp-selected'))
_login_auth |= TP_LOGIN_AUTH_USERNAME_PASSWORD_CAPTCHA;
if (_sec.dom.btn_auth_username_oath.hasClass('tp-selected'))
_login_auth |= TP_LOGIN_AUTH_USERNAME_OATH;
// if (_sec.dom.btn_auth_username_oath.hasClass('tp-selected'))
// _login_auth |= TP_LOGIN_AUTH_USERNAME_OATH;
if (_sec.dom.btn_auth_username_password_oath.hasClass('tp-selected'))
_login_auth |= TP_LOGIN_AUTH_USERNAME_PASSWORD_OATH;

View File

@ -1,6 +1,9 @@
"use strict";
$app.on_init = function (cb_stack) {
console.log($app.options);
$app.dom = {
btn_refresh_user_list: $('#btn-refresh-user-list'),
btn_create_user: $('#btn-create-user'),
@ -648,6 +651,7 @@ $app.create_dlg_edit_user = function () {
dlg.dom_id = 'dlg-edit-user';
dlg.field_id = -1; // 用户id仅编辑模式
dlg.field_role = -1;
dlg.field_auth_type = 0;
dlg.field_username = '';
dlg.field_surname = '';
dlg.field_email = '';
@ -657,18 +661,25 @@ $app.create_dlg_edit_user = function () {
dlg.field_desc = '';
dlg.dom = {
dialog: $('#' + dlg.dom_id),
dlg_title: $('#' + dlg.dom_id + ' [data-field="dlg-title"]'),
select_role: $('#edit-user-role'),
edit_username: $('#edit-user-username'),
edit_surname: $('#edit-user-surname'),
edit_email: $('#edit-user-email'),
edit_mobile: $('#edit-user-mobile'),
edit_qq: $('#edit-user-qq'),
edit_wechat: $('#edit-user-wechat'),
edit_desc: $('#edit-user-desc'),
msg: $('#edit-user-message'),
btn_save: $('#btn-edit-user-save'),
dialog: $('#' + dlg.dom_id)
, dlg_title: $('#' + dlg.dom_id + ' [data-field="dlg-title"]')
, select_role: $('#edit-user-role')
, edit_username: $('#edit-user-username')
, edit_surname: $('#edit-user-surname')
, edit_email: $('#edit-user-email')
, edit_mobile: $('#edit-user-mobile')
, edit_qq: $('#edit-user-qq')
, edit_wechat: $('#edit-user-wechat')
, edit_desc: $('#edit-user-desc')
, msg: $('#edit-user-message')
, btn_save: $('#btn-edit-user-save')
, btn_auth_use_sys_config: $('#sec-auth-use-sys-config')
// , btn_auth_username_password: $('#sec-auth-username-password')
, btn_auth_username_password_captcha: $('#sec-auth-username-password-captcha')
// , btn_auth_username_oath: $('#sec-auth-username-oath')
, btn_auth_username_password_oath: $('#sec-auth-username-password-oath')
};
dlg.init = function (cb_stack) {
@ -703,14 +714,81 @@ $app.create_dlg_edit_user = function () {
dlg.dom.selected_role.text(name);
});
dlg.dom.btn_auth_use_sys_config.click(function () {
if ($(this).hasClass('tp-selected')) {
// $(this).removeClass('tp-selected');
// dlg.dom.btn_auth_username_password.addClass('tp-editable');
// dlg.dom.btn_auth_username_password_captcha.addClass('tp-editable');
// dlg.dom.btn_auth_username_oath.addClass('tp-editable');
// dlg.dom.btn_auth_username_password_oath.addClass('tp-editable');
dlg._use_sys_auth_config(false);
} else {
dlg._use_sys_auth_config(true);
}
});
// dlg.dom.btn_auth_username_password.click(function () {
// dlg._switch_auth($(this));
// });
dlg.dom.btn_auth_username_password_captcha.click(function () {
dlg._switch_auth($(this));
});
// dlg.dom.btn_auth_username_oath.click(function () {
// dlg._switch_auth($(this));
// });
dlg.dom.btn_auth_username_password_oath.click(function () {
dlg._switch_auth($(this));
});
dlg.dom.btn_save.click(dlg.on_save);
cb_stack.exec();
};
dlg._use_sys_auth_config = function (use_sys) {
if (use_sys) {
dlg.dom.btn_auth_use_sys_config.addClass('tp-selected');
// dlg.dom.btn_auth_username_password.removeClass('tp-editable tp-selected');
dlg.dom.btn_auth_username_password_captcha.removeClass('tp-editable tp-selected');
// dlg.dom.btn_auth_username_oath.removeClass('tp-editable tp-selected');
dlg.dom.btn_auth_username_password_oath.removeClass('tp-editable tp-selected');
var auth_type = $app.options.sys_cfg.login.auth;
// if (auth_type & TP_LOGIN_AUTH_USERNAME_PASSWORD)
// dlg.dom.btn_auth_username_password.addClass('tp-selected');
if (auth_type & TP_LOGIN_AUTH_USERNAME_PASSWORD_CAPTCHA)
dlg.dom.btn_auth_username_password_captcha.addClass('tp-selected');
// if (auth_type & TP_LOGIN_AUTH_USERNAME_OATH)
// dlg.dom.btn_auth_username_oath.addClass('tp-selected');
if (auth_type & TP_LOGIN_AUTH_USERNAME_PASSWORD_OATH)
dlg.dom.btn_auth_username_password_oath.addClass('tp-selected');
} else {
dlg.dom.btn_auth_use_sys_config.removeClass('tp-selected');
// dlg.dom.btn_auth_username_password.addClass('tp-editable');
dlg.dom.btn_auth_username_password_captcha.addClass('tp-editable');
// dlg.dom.btn_auth_username_oath.addClass('tp-editable');
dlg.dom.btn_auth_username_password_oath.addClass('tp-editable');
}
};
dlg._switch_auth = function (obj) {
if (!obj.hasClass('tp-editable'))
return;
if (obj.hasClass('tp-selected')) {
obj.removeClass('tp-selected');
} else {
obj.addClass('tp-selected');
}
};
dlg.init_fields = function (user) {
var role_name = '选择角色';
dlg.field_role = -1;
dlg.field_auth_type = 0;
// dlg.dom.btn_auth_use_sys_config.removeClass('tp-selected');
// dlg.dom.btn_auth_username_password.removeClass('tp-selected');
// dlg.dom.btn_auth_username_password_captcha.removeClass('tp-selected');
// dlg.dom.btn_auth_username_oath.removeClass('tp-selected');
// dlg.dom.btn_auth_username_password_oath.removeClass('tp-selected');
if (_.isUndefined(user)) {
dlg.dom.dlg_title.html('创建用户账号');
@ -724,6 +802,7 @@ $app.create_dlg_edit_user = function () {
dlg.dom.edit_desc.val('');
} else {
dlg.field_id = user.id;
dlg.field_auth_type = user.auth_type;
dlg.dom.dlg_title.html('编辑:' + user.surname);
var _name = $app.role_id2name(user.role_id);
@ -741,6 +820,21 @@ $app.create_dlg_edit_user = function () {
dlg.dom.edit_desc.val(user.desc);
}
dlg.dom.selected_role.text(role_name);
if (dlg.field_auth_type === 0) {
dlg._use_sys_auth_config(true);
} else {
dlg._use_sys_auth_config(false);
var auth_type = dlg.field_auth_type;
// if (auth_type & TP_LOGIN_AUTH_USERNAME_PASSWORD)
// dlg.dom.btn_auth_username_password.addClass('tp-selected');
if (auth_type & TP_LOGIN_AUTH_USERNAME_PASSWORD_CAPTCHA)
dlg.dom.btn_auth_username_password_captcha.addClass('tp-selected');
// if (auth_type & TP_LOGIN_AUTH_USERNAME_OATH)
// dlg.dom.btn_auth_username_oath.addClass('tp-selected');
if (auth_type & TP_LOGIN_AUTH_USERNAME_PASSWORD_OATH)
dlg.dom.btn_auth_username_password_oath.addClass('tp-selected');
}
};
dlg.show_create = function () {
@ -774,11 +868,6 @@ $app.create_dlg_edit_user = function () {
$tp.notify_error('请指定 4~32 个英文字母和数字组成的用户账号,注意,账号不区分大小写!');
return false;
}
// if (dlg.field_email.length === 0) {
// dlg.dom.edit_email.focus();
// $tp.notify_error('请指定用户的邮箱地址!');
// return false;
// }
if (dlg.field_email.length > 0) {
if (!tp_check_email(dlg.field_email)) {
@ -788,6 +877,23 @@ $app.create_dlg_edit_user = function () {
}
}
dlg.field_auth_type = 0;
if (!dlg.dom.btn_auth_use_sys_config.hasClass('tp-selected')) {
// if (dlg.dom.btn_auth_username_password.hasClass('tp-selected'))
// dlg.field_auth_type |= TP_LOGIN_AUTH_USERNAME_PASSWORD;
if (dlg.dom.btn_auth_username_password_captcha.hasClass('tp-selected'))
dlg.field_auth_type |= TP_LOGIN_AUTH_USERNAME_PASSWORD_CAPTCHA;
// if (dlg.dom.btn_auth_username_oath.hasClass('tp-selected'))
// dlg.field_auth_type |= TP_LOGIN_AUTH_USERNAME_OATH;
if (dlg.dom.btn_auth_username_password_oath.hasClass('tp-selected'))
dlg.field_auth_type |= TP_LOGIN_AUTH_USERNAME_PASSWORD_OATH;
if(dlg.field_auth_type === 0) {
$tp.notify_error('请设置用户登录时身份验证方式!');
return false;
}
}
return true;
};
@ -799,15 +905,16 @@ $app.create_dlg_edit_user = function () {
// 如果id为-1表示创建否则表示更新
$tp.ajax_post_json('/user/update-user', {
id: dlg.field_id,
role: dlg.field_role,
username: dlg.field_username,
surname: dlg.field_surname,
email: dlg.field_email,
mobile: dlg.field_mobile,
qq: dlg.field_qq,
wechat: dlg.field_wechat,
desc: dlg.field_desc
id: dlg.field_id
, role: dlg.field_role
, auth_type: dlg.field_auth_type
, username: dlg.field_username
, surname: dlg.field_surname
, email: dlg.field_email
, mobile: dlg.field_mobile
, qq: dlg.field_qq
, wechat: dlg.field_wechat
, desc: dlg.field_desc
},
function (ret) {
if (ret.code === TPE_OK) {

View File

@ -84,8 +84,11 @@ label {
}
hr.hr-sm {
margin-top: 5px;
margin-bottom: 5px;
//margin-top: 5px;
//margin-bottom: 5px;
padding: 1px 0;
margin: 5px 0;
border-top: 1px dashed #c4c4c4;
}
ul {

View File

@ -122,7 +122,7 @@ body {
.inputarea {
margin: 30px;
.input-group-addon {
padding: 0 20px 0 5px;
padding: 0 10px;
}
p.input-addon-desc {
text-align: right;

View File

@ -1047,7 +1047,7 @@ textarea.cert_pub {
//.form-control-static
.tp-checkbox {
display: inline-block;
color: #6487ad;
color: #747474;
&.tp-disabled {
cursor: not-allowed;
@ -1063,20 +1063,24 @@ textarea.cert_pub {
font-family: 'FontAwesome';
}
&.tp-editable {
cursor: pointer;
&:hover {
color: #459dee;
}
}
&.tp-selected, &.tp-checked {
color: #3374b0;
//color: #3374b0;
&:before {
content: "\f046";
font-family: 'FontAwesome';
}
}
&.tp-editable {
cursor: pointer;
color: #459dee;
&:hover {
color: #53af43;
}
&.tp-selected, &.tp-checked {
color: #3374b0;
}
}
}
i.upload-button {

View File

@ -32,7 +32,7 @@
<div class="inputbox">
<div class="input-group input-group-lg">
<span class="input-group-addon"><i class="fa fa-user fa-fw"></i></span>
<input data-field="username" type="text" class="form-control" placeholder="账号:邮箱地址或手机号" data-toggle="popover" data-trigger="manual" data-placement="top">
<input data-field="username" type="text" class="form-control" placeholder="用户名" data-toggle="popover" data-trigger="manual" data-placement="top">
</div>
</div>
@ -58,7 +58,7 @@
<div id="login-area-oath" style="display:none;">
<div class="inputbox">
<div class="input-group input-group-lg">
<span class="input-group-addon"><i class="fa fa-clock-o fa-fw"></i></span>
<span class="input-group-addon"><i class="fa fa-shield fa-fw"></i></span>
<input id="oath-code" type="text" class="form-control" placeholder="6位数字身份验证器动态验证码" data-toggle="popover" data-trigger="manual" data-placement="top">
</div>
<p class="input-addon-desc"><a href="/user/bind-oath">尚未绑定身份验证器?</a></p>

View File

@ -41,17 +41,17 @@
<td colspan="2" class="title">密码策略</td>
</tr>
<tr>
<td class="key">找回密码</td>
<td class="key">重置密码</td>
<td class="value">
<div id="sec-allow-reset-password" class="tp-checkbox tp-editable">允许用户找回密码</div>
<span class="desc">关闭此功能,只能由管理员为用户重置密码。默认开启。</span>
<div id="sec-allow-reset-password" class="tp-checkbox tp-editable">允许用户通过邮件重置密码</div>
<span class="desc">关闭此功能,只能由管理员为用户手工重置密码。默认开启。</span>
</td>
</tr>
<tr>
<td class="key">密码强度</td>
<td class="value">
<div id="sec-force-strong-password" class="tp-checkbox tp-editable">强制使用强密码</div>
<span class="desc">至少8个英文字符必须包含大写字母、小写字母、数字和标点符号。默认开启。</span>
<span class="desc">至少8个英文字符必须包含大写字母、小写字母和数字。默认开启。</span>
</td>
</tr>
<tr>
@ -91,24 +91,24 @@
注意:可以为每个用户指定特定的认证方式。
</td>
</tr>
<tr>
<td class="key"></td>
<td class="value">
<div id="sec-auth-username-password" class="tp-checkbox tp-editable">用户名 + 密码</div>
</td>
</tr>
## <tr>
## <td class="key"></td>
## <td class="value">
## <div id="sec-auth-username-password" class="tp-checkbox tp-editable">用户名 + 密码</div>
## </td>
## </tr>
<tr>
<td class="key"></td>
<td class="value">
<div id="sec-auth-username-password-captcha" class="tp-checkbox tp-editable">用户名 + 密码 + 验证码</div>
</td>
</tr>
<tr>
<td class="key"></td>
<td class="value">
<div id="sec-auth-username-oath" class="tp-checkbox tp-editable">用户名 + 身份认证器动态密码</div>
</td>
</tr>
## <tr>
## <td class="key"></td>
## <td class="value">
## <div id="sec-auth-username-oath" class="tp-checkbox tp-editable">用户名 + 身份认证器动态密码</div>
## </td>
## </tr>
<tr>
<td class="key"></td>
<td class="value">

View File

@ -74,7 +74,7 @@
<li><em>删除用户</em> 允许删除登录teleport系统的用户。</li>
<li><em>用户禁用/解禁</em> 允许设置禁止用户访问teleport系统或者解禁。当用户因连续认证失败而被临时锁定时也可由此权限进行解锁。</li>
<li><em>用户分组管理</em> 将用户进行分组,便于快速查找或者授权管理。</li>
<li><em>远程主机运维</em> 允许用户访问远程主机。</li>
<li><em>远程主机运维</em> 允许用户访问指定的远程主机,允许用户查看、回放自己的操作录像。</li>
<li><em>运维授权管理</em> 授权用户/用户组使用特定的远程主机账号访问指定远程主机。具有本权限的用户自动具有远程主机运维的权限。</li>
<li><em>查看在线会话</em> 允许查看在线运维会话,并进行实时同步显示。【此功能尚未实现】</li>
<li><em>阻断在线会话</em> 强行终止在线运维会话。【此功能尚未实现】</li>

View File

@ -205,6 +205,24 @@
<textarea id="edit-user-desc" class="form-control" style="resize: vertical;"></textarea>
</div>
</div>
<div class="form-group form-group-sm">
<label for="edit-user-desc" class="col-sm-2 control-label">认证方式:</label>
<div class="col-sm-10">
<div class="control-desc">当前使用系统默认设置</div>
<ul class="list">
<li><div id="sec-auth-use-sys-config" class="tp-checkbox tp-editable">使用系统默认设置</div></li>
<li><hr class="hr-sm"/></li>
## <li><div id="sec-auth-username-password" class="tp-checkbox">用户名 + 密码</div></li>
<li><div id="sec-auth-username-password-captcha" class="tp-checkbox">用户名 + 密码 + 验证码</div></li>
## <li><div id="sec-auth-username-oath" class="tp-checkbox">用户名 + 身份认证器动态密码</div></li>
<li><div id="sec-auth-username-password-oath" class="tp-checkbox">用户名 + 密码 + 身份认证器动态密码</div></li>
</ul>
</div>
</div>
</div>
</div>
@ -266,7 +284,7 @@
</div>
<div class="form-group form-group-sm">
<div class="col-sm-10 col-sm-offset-1">
为用户设置新密码,并立即生效,需要通过其它方式通知用户新密码的内容
为用户设置新密码,并立即生效,需要通过其它方式告知用户新密码
</div>
</div>

View File

@ -491,7 +491,8 @@ class AppConfig(BaseAppConfig):
if not self.sys.login.is_exists('lock_timeout'):
self.sys.login.lock_timeout = 30 # 30 min
if not self.sys.login.is_exists('auth'):
self.sys.login.auth = TP_LOGIN_AUTH_USERNAME_PASSWORD_CAPTCHA | TP_LOGIN_AUTH_USERNAME_OATH | TP_LOGIN_AUTH_USERNAME_PASSWORD_OATH
# self.sys.login.auth = TP_LOGIN_AUTH_USERNAME_PASSWORD_CAPTCHA | TP_LOGIN_AUTH_USERNAME_OATH | TP_LOGIN_AUTH_USERNAME_PASSWORD_OATH
self.sys.login.auth = TP_LOGIN_AUTH_USERNAME_PASSWORD_CAPTCHA | TP_LOGIN_AUTH_USERNAME_PASSWORD_OATH
# =====================================
# SMTP相关

View File

@ -121,7 +121,7 @@ class DatabaseInit:
f.append('surname varchar(64) DEFAULT ""')
# type 1=本地账号2=LDAP待扩展
f.append('type int(11) DEFAULT 1')
# auth_type: 0=使用全局设置,1=密码+校验码2=密码+OATH
# auth_type: 0=使用全局设置,其他参考 TP_LOGIN_AUTH_XXX 系列值
f.append('auth_type int(11) DEFAULT 0')
# password: 登录密码如果是LDAP账号则忽略此字段
f.append('password varchar(128) DEFAULT ""')

View File

@ -114,6 +114,14 @@ class DoLoginHandler(TPBaseJsonHandler):
syslog.sys_log({'username': username, 'surname': username}, self.request.remote_ip, TPE_NOT_EXISTS, '登录失败,用户`{}`不存在'.format(username))
return self.write_json(err)
# 判断此用户是否被允许使用当前登录认证方式
auth_type = user_info.auth_type
if auth_type == 0:
auth_type = sys_cfg.login.auth
if (auth_type & login_type) != login_type:
return self.write_json(TPE_USER_AUTH, '不允许使用此身份认证方式')
# err, user_info = user.get_by_username(username)
# if err != TPE_OK:
# if err == TPE_NOT_EXISTS:
@ -255,101 +263,3 @@ class VerifyCaptchaHandler(TPBaseJsonHandler):
# return self.write_json(-4, '发生异常')
#
#
# class OathVerifyHandler(TPBaseUserAuthJsonHandler):
# def post(self):
# args = self.get_argument('args', None)
# if args is not None:
# try:
# args = json.loads(args)
# code = args['code']
# except:
# return self.write_json(-2, '参数错误')
# else:
# return self.write_json(-1, '参数错误')
#
# # secret = self.get_session('tmp_oath_secret', None)
# # if secret is None:
# # return self.write_json(-1, '内部错误!')
# # self.del_session('tmp_oath_secret')
#
# user_info = self.get_current_user()
# if not user.verify_oath(user_info['id'], code):
# return self.write_json(-3, '验证失败!')
# else:
# return self.write_json(0)
#
#
# class OathSecretQrCodeHandler(TPBaseUserAuthJsonHandler):
# def get(self):
# secret = self.get_session('tmp_oath_secret', None)
#
# user_info = self.get_current_user()
# img_data = tp_oath_generate_qrcode(user_info['name'], secret)
#
# # secret = '6OHEKKJPLMUBJ4EHCT5ZT5YLUQ'
# #
# # print('TOPT should be:', get_totp_token(secret))
# # # cur_input = int(time.time()) // 30
# # # print('cur-input', cur_input, int(time.time()))
# # # window = 10
# # # for i in range(cur_input - (window - 1) // 2, cur_input + window // 2 + 1): # [cur_input-(window-1)//2, cur_input + window//2]
# # # print(get_totp_token(secret, i))
# #
# # msg = 'otpauth://totp/Admin?secret={}&issuer=teleport'.format(secret)
# # qr = qrcode.QRCode(
# # version=1,
# # error_correction=qrcode.constants.ERROR_CORRECT_L,
# # box_size=4,
# # border=4,
# # )
# # qr.add_data(msg)
# # qr.make(fit=True)
# # img = qr.make_image()
# #
# # # img = qrcode.make(msg)
# # out = io.BytesIO()
# # img.save(out, "jpeg", quality=100)
# # # web.header('Content-Type','image/jpeg')
# # # img.save('test.png')
# self.set_header('Content-Type', 'image/jpeg')
# self.write(img_data)
#
#
# class OathSecretResetHandler(TPBaseUserAuthJsonHandler):
# def post(self):
# oath_secret = tp_oath_generate_secret()
# self.set_session('tmp_oath_secret', oath_secret)
# return self.write_json(0, data={"tmp_oath_secret": oath_secret})
#
#
# class OathUpdateSecretHandler(TPBaseUserAuthJsonHandler):
# def post(self):
# args = self.get_argument('args', None)
# if args is not None:
# try:
# args = json.loads(args)
# code = args['code']
# except:
# return self.write_json(-2, '参数错误')
# else:
# return self.write_json(-1, '参数错误')
#
# secret = self.get_session('tmp_oath_secret', None)
# if secret is None:
# return self.write_json(-1, '内部错误!')
# self.del_session('tmp_oath_secret')
#
# if tp_oath_verify_code(secret, code):
# user_info = self.get_current_user()
# try:
# ret = user.update_oath_secret(user_info['id'], secret)
# if 0 != ret:
# return self.write_json(ret)
# except:
# log.e('update user oath-secret failed.')
# return self.write_json(-2, '发生异常')
#
# # self.set_session('oath_secret', secret)
# return self.write_json(0)
# else:
# return self.write_json(-3, '验证失败!')

View File

@ -32,11 +32,12 @@ class UserListHandler(TPBaseHandler):
is_sys_smtp = False
if get_cfg().sys.loaded:
smtp = get_cfg().sys.smtp
if len(smtp.server) > 0 and smtp.port != -1:
if len(smtp.server) > 0:
is_sys_smtp = True
param = {
'sys_smtp': is_sys_smtp
'sys_smtp': is_sys_smtp,
'sys_cfg': get_cfg().sys
}
self.render('user/user-list.mako', page_param=json.dumps(param))
@ -182,7 +183,7 @@ class DoBindOathHandler(TPBaseJsonHandler):
if not tp_oath_verify_code(secret, oath_code):
return self.write_json(TPE_OATH_MISMATCH)
err = user.update_oath_secret(user_info['id'], secret)
err = user.update_oath_secret(self, user_info['id'], secret)
if err != TPE_OK:
return self.write_json(err)
@ -384,15 +385,15 @@ class DoImportHandler(TPBaseHandler):
failed.append({'line': line, 'error': '格式错误,用户账号必须填写。'})
continue
_auth = csv_recorder[self.IDX_AUTH_TYPE].strip()
if len(_auth) == 0:
failed.append({'line': line, 'error': '格式错误,用户认证类型必须填写。'})
continue
try:
_auth = int(_auth)
except:
failed.append({'line': line, 'error': '格式错误,用户认证类型必须是数字。'})
continue
# _auth = csv_recorder[self.IDX_AUTH_TYPE].strip()
# if len(_auth) == 0:
# failed.append({'line': line, 'error': '格式错误,用户认证类型必须填写。'})
# continue
# try:
# _auth = int(_auth)
# except:
# failed.append({'line': line, 'error': '格式错误,用户认证类型必须是数字。'})
# continue
_email = csv_recorder[self.IDX_EMAIL].strip()
# if len(_email) == 0:
@ -406,7 +407,7 @@ class DoImportHandler(TPBaseHandler):
u['_id'] = 0
u['username'] = _username
u['surname'] = csv_recorder[self.IDX_SURNAME].strip()
u['auth'] = _auth
# u['auth'] = _auth
u['email'] = _email
u['mobile'] = csv_recorder[self.IDX_MOBILE].strip()
u['qq'] = csv_recorder[self.IDX_QQ].strip()
@ -512,6 +513,7 @@ class DoUpdateUserHandler(TPBaseJsonHandler):
try:
args['id'] = int(args['id'])
args['role'] = int(args['role'])
args['auth_type'] = int(args['auth_type'])
args['username'] = args['username'].strip()
args['surname'] = args['surname'].strip()
args['email'] = args['email'].strip()

View File

@ -189,9 +189,9 @@ def create_users(handler, user_list, success, failed):
continue
sql = 'INSERT INTO `{}user` (`type`, `auth_type`, `username`, `surname`, `role_id`, `state`, `email`, `creator_id`, `create_time`, `last_login`, `last_chpass`, `desc`) VALUES ' \
'(1, {auth}, "{username}", "{surname}", 0, {state}, "{email}", {creator_id}, {create_time}, {last_login}, {last_chpass}, "{desc}");' \
'(1, 0, "{username}", "{surname}", 0, {state}, "{email}", {creator_id}, {create_time}, {last_login}, {last_chpass}, "{desc}");' \
''.format(db.table_prefix,
auth=user['auth'], username=user['username'], surname=user['surname'], state=TP_STATE_NORMAL, email=user['email'],
username=user['username'], surname=user['surname'], state=TP_STATE_NORMAL, email=user['email'],
creator_id=operator['id'], create_time=_time_now, last_login=0, last_chpass=0, desc=user['desc'])
db_ret = db.exec(sql)
if not db_ret:
@ -228,8 +228,8 @@ def create_user(handler, args):
# return TPE_EXISTS, 0
sql = 'INSERT INTO `{}user` (`type`, `auth_type`, `username`, `surname`, `role_id`, `state`, `email`, `creator_id`, `create_time`, `last_login`, `last_chpass`, `desc`) VALUES ' \
'(1, 1, "{username}", "{surname}", {role}, {state}, "{email}", {creator_id}, {create_time}, {last_login}, {last_chpass}, "{desc}");' \
''.format(db.table_prefix,
'(1, {auth_type}, "{username}", "{surname}", {role}, {state}, "{email}", {creator_id}, {create_time}, {last_login}, {last_chpass}, "{desc}");' \
''.format(db.table_prefix, auth_type=args['auth_type'],
username=args['username'], surname=args['surname'], role=args['role'], state=TP_STATE_NORMAL, email=args['email'],
creator_id=operator['id'],
create_time=_time_now, last_login=0, last_chpass=0, desc=args['desc'])
@ -256,9 +256,9 @@ def update_user(handler, args):
if db_ret is None or len(db_ret) == 0:
return TPE_NOT_EXISTS
sql = 'UPDATE `{}user` SET `surname`="{surname}", `role_id`={role}, `email`="{email}", mobile="{mobile}", qq="{qq}", wechat="{wechat}", `desc`="{desc}" WHERE id={user_id};' \
sql = 'UPDATE `{}user` SET surname="{surname}", auth_type={auth_type}, role_id={role}, email="{email}", mobile="{mobile}", qq="{qq}", wechat="{wechat}", `desc`="{desc}" WHERE id={user_id};' \
''.format(db.table_prefix,
surname=args['surname'], role=args['role'], email=args['email'],
surname=args['surname'], auth_type=args['auth_type'], role=args['role'], email=args['email'],
mobile=args['mobile'], qq=args['qq'], wechat=args['wechat'], desc=args['desc'],
user_id=args['id']
)
@ -312,7 +312,7 @@ def set_password(handler, user_id, password):
return TPE_DATABASE
if operator['id'] == 0:
syslog.sys_log({'username': name, 'surname': surname}, handler.request.remote_ip, TPE_OK, "用户 {} 通过找回密码功能重置了密码".format(name))
syslog.sys_log({'username': name, 'surname': surname}, handler.request.remote_ip, TPE_OK, "用户 {} 通过邮件方式重置了密码".format(name))
else:
syslog.sys_log(operator, handler.request.remote_ip, TPE_OK, "为用户 {} 手动重置了密码".format(name))
@ -408,10 +408,22 @@ def update_login_info(handler, user_id):
return TPE_DATABASE
def update_oath_secret(user_id, oath_secret):
def update_oath_secret(handler, user_id, oath_secret):
db = get_db()
s = SQL(db)
err = s.select_from('user', ['username', 'surname'], alt_name='u').where('u.id={user_id}'.format(user_id=user_id)).query()
if err != TPE_OK:
return err
if len(s.recorder) == 0:
return TPE_NOT_EXISTS
username = s.recorder[0].username
surname = s.recorder[0].surname
sql = 'UPDATE `{dbtp}user` SET oath_secret="{secret}" WHERE id={user_id}'.format(dbtp=db.table_prefix, secret=oath_secret, user_id=user_id)
if db.exec(sql):
syslog.sys_log({'username': username, 'surname': surname}, handler.request.remote_ip, TPE_OK, "用户 {} 绑定了身份认证器".format(username))
return TPE_OK
else:
return TPE_DATABASE