mirror of https://github.com/jumpserver/jumpserver
add admin|sys user model
commit
0e8e88fac0
|
@ -1,13 +1,14 @@
|
||||||
# coding:utf-8
|
# coding:utf-8
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals, absolute_import
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
|
||||||
class AssetGroup(models.Model):
|
class AssetGroup(models.Model):
|
||||||
name = models.CharField(max_length=64, unique=True)
|
name = models.CharField(max_length=64, unique=True, verbose_name=_('Name'))
|
||||||
created_by = models.CharField(max_length=32, blank=True, verbose_name=u"创建者")
|
created_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by'))
|
||||||
comment = models.CharField(max_length=128, blank=True, null=True)
|
comment = models.CharField(max_length=128, blank=True, verbose_name=_('Comment'))
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
@ -17,16 +18,16 @@ class AssetGroup(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class IDC(models.Model):
|
class IDC(models.Model):
|
||||||
name = models.CharField(max_length=32, verbose_name=u'机房名称')
|
name = models.CharField(max_length=32, verbose_name=_('Name'))
|
||||||
bandwidth = models.CharField(max_length=32, blank=True, verbose_name=u'机房带宽')
|
bandwidth = models.CharField(max_length=32, blank=True, verbose_name=_('Bandwidth'))
|
||||||
contact = models.CharField(max_length=16, blank=True, verbose_name=u'联系人')
|
contact = models.CharField(max_length=16, blank=True, verbose_name=_('Contact'))
|
||||||
phone = models.CharField(max_length=32, blank=True, verbose_name=u'联系电话')
|
phone = models.CharField(max_length=32, blank=True, verbose_name=_('Phone'))
|
||||||
address = models.CharField(max_length=128, blank=True, verbose_name=u"机房地址")
|
address = models.CharField(max_length=128, blank=True, verbose_name=_("Address"))
|
||||||
network = models.TextField(blank=True, verbose_name=u"IP地址段")
|
network = models.TextField(blank=True, verbose_name=_('Network'))
|
||||||
date_added = models.DateField(auto_now=True, null=True)
|
date_added = models.DateField(auto_now=True, null=True, verbose_name=_('Date added'))
|
||||||
operator = models.CharField(max_length=32, blank=True, verbose_name=u"运营商")
|
operator = models.CharField(max_length=32, blank=True, verbose_name=_('Operator'))
|
||||||
created_by = models.CharField(max_length=32, blank=True, verbose_name=u"创建者")
|
created_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by'))
|
||||||
comment = models.CharField(max_length=128, blank=True, verbose_name=u"备注")
|
comment = models.CharField(max_length=128, blank=True, verbose_name=_('Comment'))
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
@ -38,9 +39,9 @@ class IDC(models.Model):
|
||||||
class AssetExtend(models.Model):
|
class AssetExtend(models.Model):
|
||||||
key = models.CharField(max_length=64, null=True, blank=True, verbose_name=u'key')
|
key = models.CharField(max_length=64, null=True, blank=True, verbose_name=u'key')
|
||||||
value = models.CharField(max_length=64, null=True, blank=True, verbose_name=u'value')
|
value = models.CharField(max_length=64, null=True, blank=True, verbose_name=u'value')
|
||||||
created_by = models.CharField(max_length=32, blank=True, verbose_name=u"创建者")
|
created_by = models.CharField(max_length=32, blank=True, verbose_name=u"Created by")
|
||||||
date_added = models.DateTimeField(auto_now=True, null=True, blank=True)
|
date_added = models.DateTimeField(auto_now=True, null=True, blank=True)
|
||||||
comment = models.CharField(max_length=128, blank=True, verbose_name=u"备注")
|
comment = models.CharField(max_length=128, blank=True, verbose_name=u"Comment")
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
@ -50,37 +51,37 @@ class AssetExtend(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class Asset(models.Model):
|
class Asset(models.Model):
|
||||||
ip = models.CharField(max_length=32, null=True, blank=True, verbose_name="资产IP")
|
ip = models.CharField(max_length=32, blank=True, verbose_name=_('IP'))
|
||||||
other_ip = models.CharField(max_length=255, null=True, blank=True, verbose_name="其他IP")
|
other_ip = models.CharField(max_length=255, blank=True, verbose_name=_('Other IP'))
|
||||||
remote_card_ip = models.CharField(max_length=16, null=True, blank=True, verbose_name=u'远控卡IP')
|
remote_card_ip = models.CharField(max_length=16, blank=True, verbose_name=_('Remote card IP'))
|
||||||
hostname = models.CharField(max_length=128, unique=True, null=True, blank=True, verbose_name=u"主机名")
|
hostname = models.CharField(max_length=128, unique=True, blank=True, verbose_name=_('Hostname'))
|
||||||
port = models.IntegerField(null=True, blank=True, verbose_name=u"端口")
|
port = models.IntegerField(blank=True, verbose_name=_('Port'))
|
||||||
group = models.ManyToManyField(AssetGroup, null=True, blank=True, verbose_name=u"所属主机组")
|
groups = models.ManyToManyField(AssetGroup, blank=True, verbose_name=_('Asset groups'))
|
||||||
admin_user = models.ForeignKey(AdminUser, null=True, blank=True, on_delete=models.SET_NULL, verbose_name=u'管理用户')
|
username = models.CharField(max_length=16, blank=True, verbose_name=_('Admin user'))
|
||||||
sys_user = models.ManyToManyField(AssetExtend, null=True, blank=True, verbose_name="系统用户")
|
password = models.CharField(max_length=256, blank=True, verbose_name=_("Admin password"))
|
||||||
username = models.CharField(max_length=16, null=True, blank=True, verbose_name=u"管理用户名")
|
admin_user = models.ForeignKey(AdminUser, null=True, blank=True, on_delete=models.SET_NULL, verbose_name=_("Admin User"))
|
||||||
password = models.CharField(max_length=256, null=True, blank=True, verbose_name=u"密码")
|
sys_user = models.ManyToManyField(SysUser, null=True, blank=True, verbose_name=_("Sys User"))
|
||||||
idc = models.ForeignKey(IDC, null=True, blank=True, on_delete=models.SET_NULL, verbose_name=u'机房')
|
idc = models.ForeignKey(IDC, blank=True, null=True, on_delete=models.SET_NULL, verbose_name=_('IDC'))
|
||||||
mac_addr = models.CharField(max_length=20, null=True, blank=True, verbose_name=u"MAC地址")
|
mac_addr = models.CharField(max_length=20, blank=True, verbose_name=_("Mac address"))
|
||||||
brand = models.CharField(max_length=64, null=True, blank=True, verbose_name=u'硬件厂商型号')
|
brand = models.CharField(max_length=64, blank=True, verbose_name=_('Brand'))
|
||||||
cpu = models.CharField(max_length=64, null=True, blank=True, verbose_name=u'CPU')
|
cpu = models.CharField(max_length=64, blank=True, verbose_name=_('CPU'))
|
||||||
memory = models.CharField(max_length=128, null=True, blank=True, verbose_name=u'内存')
|
memory = models.CharField(max_length=128, blank=True, verbose_name=_('Memory'))
|
||||||
disk = models.CharField(max_length=1024, null=True, blank=True, verbose_name=u'硬盘')
|
disk = models.CharField(max_length=1024, blank=True, verbose_name=_('Disk'))
|
||||||
os = models.CharField(max_length=128, null=True, blank=True, verbose_name=u'系统信息')
|
os = models.CharField(max_length=128, blank=True, verbose_name=_('OS'))
|
||||||
cabinet_no = models.CharField(max_length=32, null=True, blank=True, verbose_name=u'机柜号')
|
cabinet_no = models.CharField(max_length=32, blank=True, verbose_name=_('Cabinet number'))
|
||||||
cabinet_pos = models.IntegerField(null=True, blank=True, verbose_name=u'资产位置')
|
cabinet_pos = models.IntegerField(null=True, blank=True, verbose_name=_('Cabinet position'))
|
||||||
number = models.CharField(max_length=32, null=True, blank=True, verbose_name=u'资产编号')
|
number = models.CharField(max_length=32, blank=True, unique=True, verbose_name=_('Asset number'))
|
||||||
status = models.ManyToManyField(AssetExtend, null=True, blank=True,
|
status = models.ManyToManyField(AssetExtend, blank=True,
|
||||||
related_name="asset_status_extend", verbose_name="资产状态")
|
related_name="asset_status_extend", verbose_name=_('Asset status'))
|
||||||
type = models.ManyToManyField(AssetExtend, null=True, blank=True,
|
type = models.ManyToManyField(AssetExtend, blank=True,
|
||||||
related_name="asset_type_extend", verbose_name="资产类型")
|
related_name="asset_type_extend", verbose_name=_('Asset type'))
|
||||||
env = models.ManyToManyField(AssetExtend, null=True, blank=True,
|
env = models.ManyToManyField(AssetExtend, blank=True,
|
||||||
related_name="asset_env_extend", verbose_name="资产环境")
|
related_name="asset_env_extend", verbose_name=_('Asset environment'))
|
||||||
sn = models.CharField(max_length=128, null=True, blank=True, verbose_name=u"SN编号")
|
sn = models.CharField(max_length=128, blank=True, unique=True, verbose_name=_('Serial number'))
|
||||||
created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=u"创建者")
|
created_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by'))
|
||||||
is_active = models.BooleanField(default=True, verbose_name=u"是否激活")
|
is_active = models.BooleanField(default=True, verbose_name=_('Is active'))
|
||||||
date_added = models.DateTimeField(auto_now=True, null=True, blank=True)
|
date_added = models.DateTimeField(auto_now=True, null=True, verbose_name=_('Date added'))
|
||||||
comment = models.CharField(max_length=128, null=True, blank=True, verbose_name=u"备注")
|
comment = models.CharField(max_length=128, blank=True, verbose_name=_('Comment'))
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.ip
|
return self.ip
|
||||||
|
@ -93,9 +94,9 @@ class Label(models.Model):
|
||||||
key = models.CharField(max_length=64, null=True, blank=True, verbose_name=u'key')
|
key = models.CharField(max_length=64, null=True, blank=True, verbose_name=u'key')
|
||||||
value = models.CharField(max_length=64, null=True, blank=True, verbose_name=u'value')
|
value = models.CharField(max_length=64, null=True, blank=True, verbose_name=u'value')
|
||||||
asset = models.ForeignKey(Asset, null=True, blank=True, on_delete=models.SET_NULL, verbose_name=u'label')
|
asset = models.ForeignKey(Asset, null=True, blank=True, on_delete=models.SET_NULL, verbose_name=u'label')
|
||||||
created_by = models.CharField(max_length=32, blank=True, verbose_name=u"创建者")
|
created_by = models.CharField(max_length=32, blank=True, verbose_name=_("Created by"))
|
||||||
date_added = models.DateTimeField(auto_now=True, null=True, blank=True)
|
date_added = models.DateTimeField(auto_now=True, null=True, blank=True)
|
||||||
comment = models.CharField(max_length=128, blank=True, verbose_name=u"备注")
|
comment = models.CharField(max_length=128, blank=True, verbose_name=_('Comment'))
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
@ -145,3 +146,4 @@ class SysUser(models.Model):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = 'sysuser'
|
db_table = 'sysuser'
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ from .views import *
|
||||||
# from .api import (
|
# from .api import (
|
||||||
# AssetGroupViewSet, AssetViewSet, IDCViewSet
|
# AssetGroupViewSet, AssetViewSet, IDCViewSet
|
||||||
# )
|
# )
|
||||||
|
from django.conf.urls import url,include
|
||||||
|
import views
|
||||||
# from rest_framework import routers
|
# from rest_framework import routers
|
||||||
# router = routers.DefaultRouter()
|
# router = routers.DefaultRouter()
|
||||||
# router.register(r'assetgroup', AssetGroupViewSet)
|
# router.register(r'assetgroup', AssetGroupViewSet)
|
||||||
|
@ -12,9 +14,18 @@ from .views import *
|
||||||
app_name = 'assets'
|
app_name = 'assets'
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^assets/add/$', AssetAddView.as_view(), name='asset-add'),
|
|
||||||
url(r'^$', AssetListView.as_view(), name='asset-list'),
|
url(r'^$', AssetListView.as_view(), name='asset-list'),
|
||||||
url(r'^(?P<pk>[0-9]+)/delete/$', AssetDeleteView.as_view(), name='asset-delete'),
|
url(r'^(?P<pk>[0-9]+)/delete/$', AssetDeleteView.as_view(), name='asset-delete'),
|
||||||
url(r'^(?P<pk>[0-9]+)/detail/$', AssetDetailView.as_view(), name='asset-detail'),
|
url(r'^(?P<pk>[0-9]+)/detail/$', AssetDetailView.as_view(), name='asset-detail'),
|
||||||
|
url(r'^asset', views.AssetListView.as_view(), name='asset-list'),
|
||||||
|
url(r'^asset/add$', views.AssetAddView.as_view(), name='asset-add'),
|
||||||
|
url(r'^asset/(?P<pk>[0-9]+)$', views.AssetDetailView.as_view(), name='asset-detail'),
|
||||||
|
url(r'^asset/(?P<pk>[0-9]+)$/edit', views.AssetEditView.as_view(), name='asset-edit'),
|
||||||
|
url(r'^asset/(?P<pk>[0-9]+)/delete$', views.AssetDeleteView.as_view(), name='asset-delete'),
|
||||||
|
url(r'^asset-group', views.AssetGroupListView.as_view(), name='assetgroup-list'),
|
||||||
|
url(r'^asset-group/add$', views.AssetAddView.as_view(), name='asset-add'),
|
||||||
|
url(r'^asset-group/(?P<pk>[0-9]+)$', views.AssetDetailView.as_view(), name='asset-detail'),
|
||||||
|
url(r'^asset-group/(?P<pk>[0-9]+)$/edit', views.AssetEditView.as_view(), name='asset-edit'),
|
||||||
|
url(r'^asset-group/(?P<pk>[0-9]+)/delete$', views.AssetDeleteView.as_view(), name='asset-delete'),
|
||||||
# url(r'^api/v1.0/', include(router.urls)),
|
# url(r'^api/v1.0/', include(router.urls)),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
from django.views.generic import TemplateView, ListView
|
from django.views.generic import TemplateView, ListView
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView
|
from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView
|
||||||
|
from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
|
from django.views.generic import TemplateView, ListView
|
||||||
|
from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView
|
||||||
|
from django.urls import reverse_lazy
|
||||||
from django.views.generic.detail import DetailView
|
from django.views.generic.detail import DetailView
|
||||||
from .models import Asset, AssetGroup, IDC, AssetExtend
|
from .models import Asset, AssetGroup, IDC, AssetExtend
|
||||||
from .forms import AssetForm
|
from .forms import AssetForm
|
||||||
|
@ -8,7 +13,7 @@ from .forms import AssetForm
|
||||||
from .utils import AdminUserRequiredMixin
|
from .utils import AdminUserRequiredMixin
|
||||||
|
|
||||||
|
|
||||||
class AssetAddView(AdminUserRequiredMixin, CreateView):
|
class AssetAddView(CreateView):
|
||||||
model = Asset
|
model = Asset
|
||||||
form_class = AssetForm
|
form_class = AssetForm
|
||||||
template_name = 'assets/asset_add.html'
|
template_name = 'assets/asset_add.html'
|
||||||
|
@ -19,7 +24,7 @@ class AssetAddView(AdminUserRequiredMixin, CreateView):
|
||||||
return super(AssetAddView, self).form_invalid(form)
|
return super(AssetAddView, self).form_invalid(form)
|
||||||
|
|
||||||
|
|
||||||
class AssetEditView():
|
class AssetEditView(UpdateView):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,3 +44,22 @@ class AssetDetailView(DetailView):
|
||||||
context_object_name = 'asset'
|
context_object_name = 'asset'
|
||||||
template_name = 'assets/asset_detail.html'
|
template_name = 'assets/asset_detail.html'
|
||||||
|
|
||||||
|
|
||||||
|
class AssetGroupAddView(CreateView):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class AssetGroupListView(ListView):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class AssetGroupDetailView(DetailView):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class AssetGroupEditView(UpdateView):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class AssetGroupDeleteView(DeleteView):
|
||||||
|
pass
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
{% if messages %}
|
{% if messages %}
|
||||||
<p>
|
<p>
|
||||||
<div class="alert alert-success">
|
<div class="alert alert-success" id="messages">
|
||||||
{{ messages }}
|
{{ messages }}
|
||||||
</div>
|
</div>
|
||||||
</p>
|
</p>
|
||||||
|
@ -52,9 +52,26 @@
|
||||||
Copyright Jumpserver.org
|
Copyright Jumpserver.org
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 text-right">
|
<div class="col-md-6 text-right">
|
||||||
<small>© 2014-2016</small>
|
<small>2014-2016</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
<script>
|
||||||
|
var time=5;
|
||||||
|
function redirect_page() {
|
||||||
|
if (time >= 0) {
|
||||||
|
var messages = '{{ messages }}, <b>' + time +'</b> ...';
|
||||||
|
$('#messages').html(messages);
|
||||||
|
time--;
|
||||||
|
setTimeout(redirect_page, 1000);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
window.location.href = "{{ redirect_url }}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{% if auto_redirect %}
|
||||||
|
window.onload = redirect_page;
|
||||||
|
{% endif %}
|
||||||
|
</script>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
[{"model": "users.role", "pk": 1, "fields": {"name": "Administrator", "date_added": "2016-08-20T17:03:42.631Z", "created_by": "System", "comment": "\u7ba1\u7406\u5458", "permissions": [16, 17, 18, 19, 20, 21, 10, 11, 12, 13, 14, 15, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 1, 2, 3, 4, 5, 6, 7, 8, 9]}}, {"model": "users.role", "pk": 2, "fields": {"name": "User", "date_added": "2016-08-20T17:03:42.671Z", "created_by": "System", "comment": "\u7528\u6237", "permissions": []}}, {"model": "users.role", "pk": 3, "fields": {"name": "Auditor", "date_added": "2016-08-20T17:03:42.683Z", "created_by": "System", "comment": "\u5ba1\u8ba1\u5458", "permissions": []}}, {"model": "users.usergroup", "pk": 1, "fields": {"name": "ALL", "comment": "Default usergroup for all user", "date_added": "2016-08-20T17:03:42.693Z", "created_by": "System"}}, {"model": "users.user", "pk": 1, "fields": {"password": "pbkdf2_sha256$30000$xZUhPadgI8rs$n2rm5futcOv7Ww4b4BflN8K90Vk3u7ozfnOS7GQq0ns=", "last_login": null, "is_superuser": false, "first_name": "", "last_name": "", "is_staff": false, "is_active": true, "date_joined": "2016-08-20T17:03:42.752Z", "username": "admin", "name": "Administrator", "email": "admin@jumpserver.org", "avatar": "", "wechat": "", "phone": "", "enable_otp": false, "secret_key_otp": "", "role": 1, "private_key": "", "public_key": "", "comment": "Administrator is the super user of system", "date_expired": "2086-08-03T17:03:42.753Z", "created_by": "System", "user_permissions": [], "groups": [1]}}][{"model": "users.usergroup", "pk": 1, "fields": {"name": "Default", "comment": "Default user group for all user", "date_added": "2016-08-24T08:24:34.436Z", "created_by": "System"}}, {"model": "users.user", "pk": 1, "fields": {"password": "pbkdf2_sha256$30000$MC3vobX7pa0C$l9qIj4UwHqODnj1hMvVy9DjLxbBumZaioQWIFrWQR7c=", "last_login": null, "first_name": "", "last_name": "", "is_active": true, "date_joined": "2016-08-24T08:24:34.438Z", "username": "admin", "name": "Administrator", "email": "admin@jumpserver.org", "role": "Admin", "avatar": "", "wechat": "", "phone": "", "enable_otp": false, "secret_key_otp": "", "private_key": "", "public_key": "", "comment": "Administrator is the super user of system", "date_expired": "2086-08-07T08:24:34.438Z", "created_by": "System", "user_permissions": [], "groups": [1]}}]
|
[{"model": "users.usergroup", "pk": 1, "fields": {"name": "Default", "comment": "Default user group for all user", "date_added": "2016-09-02T14:32:32Z", "created_by": "System"}}, {"model": "users.user", "pk": 1, "fields": {"password": "pbkdf2_sha256$30000$QU8p6Y6ep8VP$Zhrgn0Issfc8ozrNSdSGmyb3X7lRAbc3EEWdc2RTj/M=", "last_login": null, "first_name": "", "last_name": "", "is_active": true, "date_joined": "2016-09-02T14:32:32Z", "username": "admin", "name": "Administrator", "email": "admin@jumpserver.org", "role": "Admin", "avatar": "", "wechat": "", "phone": "", "enable_otp": false, "secret_key_otp": "", "private_key": "", "public_key": "", "comment": "Administrator is the super user of system", "is_first_login": false, "date_expired": "2086-08-16T14:32:32Z", "created_by": "System", "user_permissions": [], "groups": [1]}}]
|
File diff suppressed because one or more lines are too long
|
@ -61,6 +61,7 @@ INSTALLED_APPS = [
|
||||||
'rest_framework',
|
'rest_framework',
|
||||||
'rest_framework.authtoken',
|
'rest_framework.authtoken',
|
||||||
'bootstrapform',
|
'bootstrapform',
|
||||||
|
'captcha',
|
||||||
# 'django.contrib.admin',
|
# 'django.contrib.admin',
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
'django.contrib.contenttypes',
|
'django.contrib.contenttypes',
|
||||||
|
@ -79,6 +80,7 @@ MIDDLEWARE = [
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
|
'django.middleware.locale.LocaleMiddleware',
|
||||||
]
|
]
|
||||||
|
|
||||||
ROOT_URLCONF = 'jumpserver.urls'
|
ROOT_URLCONF = 'jumpserver.urls'
|
||||||
|
@ -213,7 +215,7 @@ LOGGING = {
|
||||||
# Internationalization
|
# Internationalization
|
||||||
# https://docs.djangoproject.com/en/1.10/topics/i18n/
|
# https://docs.djangoproject.com/en/1.10/topics/i18n/
|
||||||
|
|
||||||
LANGUAGE_CODE = 'en-us'
|
LANGUAGE_CODE = 'zh_CN'
|
||||||
|
|
||||||
TIME_ZONE = 'Asia/Shanghai'
|
TIME_ZONE = 'Asia/Shanghai'
|
||||||
|
|
||||||
|
@ -223,6 +225,9 @@ USE_L10N = True
|
||||||
|
|
||||||
USE_TZ = True
|
USE_TZ = True
|
||||||
|
|
||||||
|
# I18N translation
|
||||||
|
LOCALE_PATHS = [os.path.join(BASE_DIR, 'locale'),]
|
||||||
|
|
||||||
# Static files (CSS, JavaScript, Images)
|
# Static files (CSS, JavaScript, Images)
|
||||||
# https://docs.djangoproject.com/en/1.10/howto/static-files/
|
# https://docs.djangoproject.com/en/1.10/howto/static-files/
|
||||||
|
|
||||||
|
@ -244,7 +249,6 @@ BOOTSTRAP_COLUMN_COUNT = 11
|
||||||
# Init data or generate fake data source for development
|
# Init data or generate fake data source for development
|
||||||
FIXTURE_DIRS = [os.path.join(BASE_DIR, 'fixtures'), ]
|
FIXTURE_DIRS = [os.path.join(BASE_DIR, 'fixtures'), ]
|
||||||
|
|
||||||
|
|
||||||
# Email config
|
# Email config
|
||||||
EMAIL_HOST = CONFIG.EMAIL_HOST
|
EMAIL_HOST = CONFIG.EMAIL_HOST
|
||||||
EMAIL_PORT = CONFIG.EMAIL_PORT
|
EMAIL_PORT = CONFIG.EMAIL_PORT
|
||||||
|
@ -302,3 +306,9 @@ BROKER_URL = 'redis://%(password)s%(host)s:%(port)s/3' % {
|
||||||
}
|
}
|
||||||
|
|
||||||
CELERY_RESULT_BACKEND = BROKER_URL
|
CELERY_RESULT_BACKEND = BROKER_URL
|
||||||
|
|
||||||
|
# Captcha settings, more see https://django-simple-captcha.readthedocs.io/en/latest/advanced.html
|
||||||
|
CAPTCHA_IMAGE_SIZE = (75, 33)
|
||||||
|
CAPTCHA_FOREGROUND_COLOR = '#001100'
|
||||||
|
|
||||||
|
#
|
||||||
|
|
|
@ -20,22 +20,14 @@ from django.views.generic.base import TemplateView
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
|
|
||||||
|
|
||||||
# def view(request, **kwargs):
|
|
||||||
# if kwargs:
|
|
||||||
# print kwargs
|
|
||||||
# return HttpResponseRedirect('/' + kwargs["module"] + '/' + kwargs["version"] + '/' + kwargs["api"])
|
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
url(r'^captcha/', include('captcha.urls')),
|
||||||
url(r'^$', TemplateView.as_view(template_name='base.html'), name='index'),
|
url(r'^$', TemplateView.as_view(template_name='base.html'), name='index'),
|
||||||
url(r'^(api/)?users/', include('users.urls')),
|
url(r'^(api/)?users/', include('users.urls')),
|
||||||
url(r'^assets/', include('assets.urls')),
|
url(r'^assets/', include('assets.urls')),
|
||||||
url(r'^terminal/', include('webterminal.urls')),
|
url(r'^terminal/', include('webterminal.urls')),
|
||||||
]
|
]
|
||||||
|
|
||||||
#urlpatterns += [
|
|
||||||
# url(r'^api/users/', include('users.api_urls')),
|
|
||||||
#]
|
|
||||||
|
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,515 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2016-09-04 17:31+0800\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: assets/models.py:9 assets/models.py:21
|
||||||
|
msgid "Name"
|
||||||
|
msgstr "名称"
|
||||||
|
|
||||||
|
#: assets/models.py:10 assets/models.py:29 assets/models.py:71
|
||||||
|
msgid "Created by"
|
||||||
|
msgstr "创建者"
|
||||||
|
|
||||||
|
#: assets/models.py:11 assets/models.py:30 assets/models.py:74
|
||||||
|
msgid "Comment"
|
||||||
|
msgstr "备注"
|
||||||
|
|
||||||
|
#: assets/models.py:22
|
||||||
|
msgid "Bandwidth"
|
||||||
|
msgstr "带宽"
|
||||||
|
|
||||||
|
#: assets/models.py:23
|
||||||
|
msgid "Contact"
|
||||||
|
msgstr "联系人"
|
||||||
|
|
||||||
|
#: assets/models.py:24
|
||||||
|
msgid "Phone"
|
||||||
|
msgstr "手机"
|
||||||
|
|
||||||
|
#: assets/models.py:25
|
||||||
|
msgid "Address"
|
||||||
|
msgstr "地址"
|
||||||
|
|
||||||
|
#: assets/models.py:26
|
||||||
|
msgid "Network"
|
||||||
|
msgstr "网络"
|
||||||
|
|
||||||
|
#: assets/models.py:27 assets/models.py:73
|
||||||
|
msgid "Date added"
|
||||||
|
msgstr "加入日期"
|
||||||
|
|
||||||
|
#: assets/models.py:28
|
||||||
|
msgid "Operator"
|
||||||
|
msgstr "运营商"
|
||||||
|
|
||||||
|
#: assets/models.py:37 assets/models.py:54 templates/_nav.html:23
|
||||||
|
msgid "IDC"
|
||||||
|
msgstr "机房"
|
||||||
|
|
||||||
|
#: assets/models.py:46
|
||||||
|
msgid "IP"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: assets/models.py:47
|
||||||
|
msgid "Other IP"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: assets/models.py:48
|
||||||
|
msgid "Remote card IP"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: assets/models.py:49
|
||||||
|
msgid "Hostname"
|
||||||
|
msgstr "用户名"
|
||||||
|
|
||||||
|
#: assets/models.py:50
|
||||||
|
msgid "Port"
|
||||||
|
msgstr "端口"
|
||||||
|
|
||||||
|
#: assets/models.py:51
|
||||||
|
msgid "Asset groups"
|
||||||
|
msgstr "用户组"
|
||||||
|
|
||||||
|
#: assets/models.py:52
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Edit user"
|
||||||
|
msgid "Admin user"
|
||||||
|
msgstr "编辑用户"
|
||||||
|
|
||||||
|
#: assets/models.py:53
|
||||||
|
msgid "Admin password"
|
||||||
|
msgstr "管理员密码"
|
||||||
|
|
||||||
|
#: assets/models.py:55
|
||||||
|
msgid "Mac address"
|
||||||
|
msgstr "Mac地址"
|
||||||
|
|
||||||
|
#: assets/models.py:56
|
||||||
|
msgid "Brand"
|
||||||
|
msgstr "品牌"
|
||||||
|
|
||||||
|
#: assets/models.py:57
|
||||||
|
msgid "CPU"
|
||||||
|
msgstr "CPU"
|
||||||
|
|
||||||
|
#: assets/models.py:58
|
||||||
|
msgid "Memory"
|
||||||
|
msgstr "内存"
|
||||||
|
|
||||||
|
#: assets/models.py:59
|
||||||
|
msgid "Disk"
|
||||||
|
msgstr "硬盘"
|
||||||
|
|
||||||
|
#: assets/models.py:60
|
||||||
|
msgid "OS"
|
||||||
|
msgstr "操作系统"
|
||||||
|
|
||||||
|
#: assets/models.py:61
|
||||||
|
msgid "Cabinet number"
|
||||||
|
msgstr "机柜编号"
|
||||||
|
|
||||||
|
#: assets/models.py:62
|
||||||
|
msgid "Cabinet position"
|
||||||
|
msgstr "机柜层号"
|
||||||
|
|
||||||
|
#: assets/models.py:63
|
||||||
|
msgid "Asset number"
|
||||||
|
msgstr "资产编号"
|
||||||
|
|
||||||
|
#: assets/models.py:65
|
||||||
|
msgid "Asset status"
|
||||||
|
msgstr "资产状态"
|
||||||
|
|
||||||
|
#: assets/models.py:67
|
||||||
|
msgid "Asset type"
|
||||||
|
msgstr "系统类型"
|
||||||
|
|
||||||
|
#: assets/models.py:69
|
||||||
|
msgid "Asset environment"
|
||||||
|
msgstr "资产环境"
|
||||||
|
|
||||||
|
#: assets/models.py:70
|
||||||
|
msgid "Serial number"
|
||||||
|
msgstr "序列号"
|
||||||
|
|
||||||
|
#: assets/models.py:72
|
||||||
|
msgid "Is active"
|
||||||
|
msgstr "是否激活"
|
||||||
|
|
||||||
|
#: templates/_header_bar.html:8
|
||||||
|
msgid "Search"
|
||||||
|
msgstr "搜索"
|
||||||
|
|
||||||
|
#: templates/_header_bar.html:14
|
||||||
|
msgid "Welcome use Jumpserver system"
|
||||||
|
msgstr "欢迎使用Jumpserver开源跳板机系统"
|
||||||
|
|
||||||
|
#: templates/_header_bar.html:18
|
||||||
|
msgid "Help"
|
||||||
|
msgstr "帮助"
|
||||||
|
|
||||||
|
#: templates/_header_bar.html:35 templates/_nav.html:4
|
||||||
|
msgid "Home"
|
||||||
|
msgstr "仪表盘"
|
||||||
|
|
||||||
|
#: templates/_nav.html:9
|
||||||
|
msgid "Users"
|
||||||
|
msgstr "用户管理"
|
||||||
|
|
||||||
|
#: templates/_nav.html:12
|
||||||
|
msgid "User"
|
||||||
|
msgstr "用户"
|
||||||
|
|
||||||
|
#: templates/_nav.html:13
|
||||||
|
msgid "Usergroup"
|
||||||
|
msgstr "用户组"
|
||||||
|
|
||||||
|
#: templates/_nav.html:18
|
||||||
|
msgid "Assets"
|
||||||
|
msgstr "资产管理"
|
||||||
|
|
||||||
|
#: templates/_nav.html:21
|
||||||
|
msgid "Asset"
|
||||||
|
msgstr "资产"
|
||||||
|
|
||||||
|
#: templates/_nav.html:22
|
||||||
|
msgid "Assetgroup"
|
||||||
|
msgstr "用户组"
|
||||||
|
|
||||||
|
#: templates/_nav.html:24
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Asset admin"
|
||||||
|
msgid "Assetadmin"
|
||||||
|
msgstr "管理用户"
|
||||||
|
|
||||||
|
#: templates/_nav.html:25
|
||||||
|
#, fuzzy
|
||||||
|
#| msgid "Asset user"
|
||||||
|
msgid "Assetuser"
|
||||||
|
msgstr "系统用户"
|
||||||
|
|
||||||
|
#: templates/_nav.html:26
|
||||||
|
msgid "Label"
|
||||||
|
msgstr "标签"
|
||||||
|
|
||||||
|
#: templates/_nav.html:30
|
||||||
|
msgid "Perms"
|
||||||
|
msgstr "权限管理"
|
||||||
|
|
||||||
|
#: templates/_nav.html:33
|
||||||
|
msgid "Perm"
|
||||||
|
msgstr "权限"
|
||||||
|
|
||||||
|
#: templates/_nav.html:36
|
||||||
|
msgid "Create perm"
|
||||||
|
msgstr "创建权限"
|
||||||
|
|
||||||
|
#: templates/_nav.html:42
|
||||||
|
msgid "Audits"
|
||||||
|
msgstr "审计"
|
||||||
|
|
||||||
|
#: templates/_nav.html:47
|
||||||
|
msgid "File"
|
||||||
|
msgstr "文件"
|
||||||
|
|
||||||
|
#: templates/_nav.html:50
|
||||||
|
msgid "File upload"
|
||||||
|
msgstr "文件上传"
|
||||||
|
|
||||||
|
#: templates/_nav.html:51
|
||||||
|
msgid "File download"
|
||||||
|
msgstr "文件下载"
|
||||||
|
|
||||||
|
#: templates/_nav.html:56
|
||||||
|
msgid "Settings"
|
||||||
|
msgstr "设置"
|
||||||
|
|
||||||
|
#: templates/_nav.html:61
|
||||||
|
msgid "Visit us"
|
||||||
|
msgstr "访问官网"
|
||||||
|
|
||||||
|
#: templates/_user_profile.html:19
|
||||||
|
msgid "Profile"
|
||||||
|
msgstr "个人信息"
|
||||||
|
|
||||||
|
#: templates/_user_profile.html:21
|
||||||
|
msgid "Logout"
|
||||||
|
msgstr "注销登录"
|
||||||
|
|
||||||
|
#: templates/captcha/image.html:3
|
||||||
|
msgid "Play CAPTCHA as audio file"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#~ msgid "Asset user"
|
||||||
|
#~ msgstr "系统用户"
|
||||||
|
|
||||||
|
#~ msgid "Password"
|
||||||
|
#~ msgstr "密码"
|
||||||
|
|
||||||
|
#~ msgid "Join usergroups"
|
||||||
|
#~ msgstr "添加到用户组"
|
||||||
|
|
||||||
|
#~ msgid "Administrator"
|
||||||
|
#~ msgstr "管理员"
|
||||||
|
|
||||||
|
#~ msgid "Email"
|
||||||
|
#~ msgstr "邮件"
|
||||||
|
|
||||||
|
#~ msgid "Role"
|
||||||
|
#~ msgstr "角色"
|
||||||
|
|
||||||
|
#~ msgid "Avatar"
|
||||||
|
#~ msgstr "头像"
|
||||||
|
|
||||||
|
#~ msgid "Wechat"
|
||||||
|
#~ msgstr "微信"
|
||||||
|
|
||||||
|
#~ msgid "Enable OTP"
|
||||||
|
#~ msgstr "二次验证"
|
||||||
|
|
||||||
|
#~ msgid "ssh private key"
|
||||||
|
#~ msgstr "ssh密钥"
|
||||||
|
|
||||||
|
#~ msgid "ssh public key"
|
||||||
|
#~ msgstr "ssh公钥"
|
||||||
|
|
||||||
|
#~ msgid "Date expired"
|
||||||
|
#~ msgstr "失效日期"
|
||||||
|
|
||||||
|
#~ msgid "Administrator is the super user of system"
|
||||||
|
#~ msgstr "Administrator是初始的超级管理员"
|
||||||
|
|
||||||
|
#~ msgid "System"
|
||||||
|
#~ msgstr "系统"
|
||||||
|
|
||||||
|
#~ msgid "Create user"
|
||||||
|
#~ msgstr "创建用户"
|
||||||
|
|
||||||
|
#~ msgid "Account"
|
||||||
|
#~ msgstr "账户"
|
||||||
|
|
||||||
|
#~ msgid "Security and Role"
|
||||||
|
#~ msgstr "角色安全"
|
||||||
|
|
||||||
|
#~ msgid "Reset"
|
||||||
|
#~ msgstr "重置"
|
||||||
|
|
||||||
|
#~ msgid "Commit"
|
||||||
|
#~ msgstr "提交"
|
||||||
|
|
||||||
|
#~ msgid "Forget password"
|
||||||
|
#~ msgstr "忘记密码"
|
||||||
|
|
||||||
|
#~ msgid "Input your email, that will send a mail to your"
|
||||||
|
#~ msgstr "输入您的邮箱, 将会发一封重置短信邮件到您的邮箱中"
|
||||||
|
|
||||||
|
#~ msgid "Login"
|
||||||
|
#~ msgstr "登录"
|
||||||
|
|
||||||
|
#~ msgid "Captcha invalid"
|
||||||
|
#~ msgstr "验证码错误"
|
||||||
|
|
||||||
|
#~ msgid "Password again"
|
||||||
|
#~ msgstr "再次输入密码"
|
||||||
|
|
||||||
|
#~ msgid "Setting"
|
||||||
|
#~ msgstr "设置"
|
||||||
|
|
||||||
|
#~ msgid "Reset link will be generated and sent to the user. "
|
||||||
|
#~ msgstr "生成重置密码连接,通过邮件发送给用户"
|
||||||
|
|
||||||
|
#~ msgid "Confirm delete"
|
||||||
|
#~ msgstr "确认删除"
|
||||||
|
|
||||||
|
#~ msgid "User detail"
|
||||||
|
#~ msgstr "用户详情"
|
||||||
|
|
||||||
|
#~ msgid "User assets"
|
||||||
|
#~ msgstr "用户资产"
|
||||||
|
|
||||||
|
#~ msgid "User log"
|
||||||
|
#~ msgstr "登录日志"
|
||||||
|
|
||||||
|
#~ msgid "Last login"
|
||||||
|
#~ msgstr "最后登录"
|
||||||
|
|
||||||
|
#~ msgid "Quick modify"
|
||||||
|
#~ msgstr "快速修改"
|
||||||
|
|
||||||
|
#~ msgid "Reset ssh key"
|
||||||
|
#~ msgstr "重置密钥"
|
||||||
|
|
||||||
|
#~ msgid "Select usergroups"
|
||||||
|
#~ msgstr "选择用户组"
|
||||||
|
|
||||||
|
#~ msgid "Add"
|
||||||
|
#~ msgstr "添加"
|
||||||
|
|
||||||
|
#~ msgid "Edit"
|
||||||
|
#~ msgstr "编辑"
|
||||||
|
|
||||||
|
#~ msgid "Delete"
|
||||||
|
#~ msgstr "删除"
|
||||||
|
|
||||||
|
#~ msgid "Delete selected"
|
||||||
|
#~ msgstr "批量删除"
|
||||||
|
|
||||||
|
#~ msgid "Update selected"
|
||||||
|
#~ msgstr "批量更新"
|
||||||
|
|
||||||
|
#~ msgid "Deactive selected"
|
||||||
|
#~ msgstr "禁用所选"
|
||||||
|
|
||||||
|
#~ msgid "Export selected"
|
||||||
|
#~ msgstr "批量导出"
|
||||||
|
|
||||||
|
#~ msgid "Begin to generate ssh private key ..."
|
||||||
|
#~ msgstr "开始生成ssh密钥"
|
||||||
|
|
||||||
|
#~ msgid "Finish to generate ssh private key ..."
|
||||||
|
#~ msgstr "生成ssh密钥成功"
|
||||||
|
|
||||||
|
#~ msgid "These is error when generate ssh key."
|
||||||
|
#~ msgstr "创建密钥失败"
|
||||||
|
|
||||||
|
#~ msgid "Create account successfully"
|
||||||
|
#~ msgstr "创建账户成功"
|
||||||
|
|
||||||
|
#~ msgid ""
|
||||||
|
#~ "\n"
|
||||||
|
#~ " Hello %(name)s:\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " Your account has been created successfully\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " <a href=\"%(rest_password_url)s?token=%(rest_password_token)s\">click "
|
||||||
|
#~ "here to set your password</a>\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " This link is valid for 1 hour. After it expires, <a href="
|
||||||
|
#~ "\"%(forget_password_url)s?email=%(email)s\">request new one</a>\n"
|
||||||
|
#~ "\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " ---\n"
|
||||||
|
#~ "\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " <a href=\"%(login_url)s\">Login direct</a>\n"
|
||||||
|
#~ "\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " "
|
||||||
|
#~ msgstr ""
|
||||||
|
#~ "\n"
|
||||||
|
#~ " 你好 %(name)s:\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " 恭喜您,您的账号已经创建成功 </br>\n"
|
||||||
|
#~ " <a href=\"%(rest_password_url)s?token=%(rest_password_token)s\">请点"
|
||||||
|
#~ "击这里设置密码</a> </br>\n"
|
||||||
|
#~ " 这个链接有效期1小时, 超过时间您可以 <a href=\"%(forget_password_url)s?"
|
||||||
|
#~ "email=%(email)s\">重新申请</a>\n"
|
||||||
|
#~ "\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " ---\n"
|
||||||
|
#~ "\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " <a href=\"%(login_url)s\">Login direct</a>\n"
|
||||||
|
#~ "\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " "
|
||||||
|
|
||||||
|
#~ msgid ""
|
||||||
|
#~ "\n"
|
||||||
|
#~ " Hello %(name)s:\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " Please click the link below to reset your password, if not your "
|
||||||
|
#~ "request, concern your account security\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " <a href=\"%(rest_password_url)s?token=%(rest_password_token)s\">Click "
|
||||||
|
#~ "here reset password</a>\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " This link is valid for 1 hour. After it expires, <a href="
|
||||||
|
#~ "\"%(forget_password_url)s?email=%(email)s\">request new one<</a>\n"
|
||||||
|
#~ "\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " ---\n"
|
||||||
|
#~ "\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " <a href=\"%(login_url)s\">Login direct</a>\n"
|
||||||
|
#~ "\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " "
|
||||||
|
#~ msgstr ""
|
||||||
|
#~ "\n"
|
||||||
|
#~ " 您好 %(name)s:\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " 请点击下面链接重置密码, 如果不是您申请的,请关注账号安全\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " <a href=\"%(rest_password_url)s?token=%(rest_password_token)s\">请点击"
|
||||||
|
#~ "这里设置密码 /a>\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " 这个链接有效期1小时, 超过时间您可以<a href=\"%(forget_password_url)s?"
|
||||||
|
#~ "email=%(email)s\">重新申请</a>\n"
|
||||||
|
#~ "\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " ---\n"
|
||||||
|
#~ "\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " <a href=\"%(login_url)s\">直接登录</a>\n"
|
||||||
|
#~ "\n"
|
||||||
|
#~ " </br>\n"
|
||||||
|
#~ " "
|
||||||
|
|
||||||
|
#~ msgid "Username or password invalid"
|
||||||
|
#~ msgstr "用户名或密码错误"
|
||||||
|
|
||||||
|
#~ msgid "Logout success"
|
||||||
|
#~ msgstr "退出登录成功"
|
||||||
|
|
||||||
|
#~ msgid "Logout success, return login page"
|
||||||
|
#~ msgstr "退出登录成功,返回到登录页面"
|
||||||
|
|
||||||
|
#~ msgid "User list"
|
||||||
|
#~ msgstr "用户列表"
|
||||||
|
|
||||||
|
#~ msgid "Create user<a href=\"%s\">%s</a> success."
|
||||||
|
#~ msgstr "创建用户<a href=\"%s\">%s</a> 成功"
|
||||||
|
|
||||||
|
#~ msgid "Usergroup list"
|
||||||
|
#~ msgstr "用户组列表"
|
||||||
|
|
||||||
|
#~ msgid "Create usergroup"
|
||||||
|
#~ msgstr "创建用户组"
|
||||||
|
|
||||||
|
#~ msgid "Email address invalid, input again"
|
||||||
|
#~ msgstr "邮箱地址错误,重新输入"
|
||||||
|
|
||||||
|
#~ msgid "Send reset password message"
|
||||||
|
#~ msgstr "发送重置密码邮件"
|
||||||
|
|
||||||
|
#~ msgid "Send reset password mail success, login your mail box and follow it "
|
||||||
|
#~ msgstr ""
|
||||||
|
#~ "发送重置邮件成功, 请登录邮箱查看, 按照提示操作 (如果没收到,请等待3-5分钟)"
|
||||||
|
|
||||||
|
#~ msgid "Reset password success"
|
||||||
|
#~ msgstr "重置密码成功"
|
||||||
|
|
||||||
|
#~ msgid "Reset password success, return to login page"
|
||||||
|
#~ msgstr "重置密码成功,返回到登录页面"
|
||||||
|
|
||||||
|
#~ msgid "Token invalid or expired"
|
||||||
|
#~ msgstr "Token错误或失效"
|
||||||
|
|
||||||
|
#~ msgid "Password not same"
|
||||||
|
#~ msgstr "密码不一致"
|
|
@ -1,20 +1,21 @@
|
||||||
|
{% load i18n %}
|
||||||
<div class="row border-bottom">
|
<div class="row border-bottom">
|
||||||
<nav class="navbar navbar-static-top white-bg" role="navigation" style="margin-bottom: 0">
|
<nav class="navbar navbar-static-top white-bg" role="navigation" style="margin-bottom: 0">
|
||||||
<div class="navbar-header">
|
<div class="navbar-header">
|
||||||
<a class="navbar-minimalize minimalize-styl-2 btn btn-primary " href="#"><i class="fa fa-bars"></i> </a>
|
<a class="navbar-minimalize minimalize-styl-2 btn btn-primary " href="#"><i class="fa fa-bars"></i> </a>
|
||||||
<form role="search" class="navbar-form-custom" method="get" action="">
|
<form role="search" class="navbar-form-custom" method="get" action="">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="text" placeholder="输入搜索..." class="form-control" name="search" id="top-search">
|
<input type="text" placeholder="{% trans 'Search' %}..." class="form-control" name="search" id="top-search">
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<ul class="nav navbar-top-links navbar-right">
|
<ul class="nav navbar-top-links navbar-right">
|
||||||
<li>
|
<li>
|
||||||
<span class="m-r-sm text-muted welcome-message">欢迎使用Jumpserver开源跳板机系统</span>
|
<span class="m-r-sm text-muted welcome-message">{% trans 'Welcome use Jumpserver system' %}</span>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<a class="dropdown-toggle count-info" data-toggle="dropdown" href="#">
|
<a class="dropdown-toggle count-info" data-toggle="dropdown" href="#">
|
||||||
<span class="m-r-sm text-muted welcome-message">帮助</span>
|
<span class="m-r-sm text-muted welcome-message">{% trans 'Help' %}</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
@ -31,7 +32,7 @@
|
||||||
<h2></h2>
|
<h2></h2>
|
||||||
<ol class="breadcrumb">
|
<ol class="breadcrumb">
|
||||||
<li>
|
<li>
|
||||||
<a href="">仪表盘</a>
|
<a href="">{% trans 'Home' %}</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
{% if app %}
|
{% if app %}
|
||||||
|
|
|
@ -1,62 +1,63 @@
|
||||||
|
{% load i18n %}
|
||||||
<li id="index">
|
<li id="index">
|
||||||
<a href="">
|
<a href="">
|
||||||
<i class="fa fa-dashboard"></i> <span class="nav-label">仪表盘</span><span class="label label-info pull-right"></span>
|
<i class="fa fa-dashboard"></i> <span class="nav-label">{% trans 'Home' %}</span><span class="label label-info pull-right"></span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li id="users">
|
<li id="users">
|
||||||
<a href="#">
|
<a href="#">
|
||||||
<i class="fa fa-group"></i> <span class="nav-label">用户管理</span><span class="fa arrow"></span>
|
<i class="fa fa-group"></i> <span class="nav-label">{% trans 'Users' %}</span><span class="fa arrow"></span>
|
||||||
</a>
|
</a>
|
||||||
<ul class="nav nav-second-level active">
|
<ul class="nav nav-second-level active">
|
||||||
<li class="users"><a href="{% url 'users:user-list' %}">用户列表</a></li>
|
<li class="users"><a href="{% url 'users:user-list' %}">{% trans 'User' %}</a></li>
|
||||||
<li class="usergroups"><a href="{% url 'users:usergroup-list' %}">用户组列表</a></li>
|
<li class="usergroups"><a href="{% url 'users:usergroup-list' %}">{% trans 'Usergroup' %}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li id="">
|
<li id="">
|
||||||
<a>
|
<a>
|
||||||
<i class="fa fa-inbox"></i> <span class="nav-label">资产管理</span><span class="fa arrow"></span>
|
<i class="fa fa-inbox"></i> <span class="nav-label">{% trans 'Assets' %}</span><span class="fa arrow"></span>
|
||||||
</a>
|
</a>
|
||||||
<ul class="nav nav-second-level">
|
<ul class="nav nav-second-level">
|
||||||
<li class=""><a href="">资产列表</a></li>
|
<li class=""><a href="">{% trans 'Asset' %}</a></li>
|
||||||
<li class=""><a href="">资产组列表</a></li>
|
<li class=""><a href="">{% trans 'Assetgroup' %}</a></li>
|
||||||
<li class=""><a href="">机房列表</a></li>
|
<li class=""><a href="">{% trans 'IDC' %}</a></li>
|
||||||
<li class=""><a href="">管理用户</a></li>
|
<li class=""><a href="">{% trans 'Assetadmin' %}</a></li>
|
||||||
<li class=""><a href="">系统用户</a></li>
|
<li class=""><a href="">{% trans 'Assetuser' %}</a></li>
|
||||||
<li class=""><a href="">标签列表</a></li>
|
<li class=""><a href="">{% trans 'Label' %}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li id="">
|
<li id="">
|
||||||
<a href="#"><i class="fa fa-edit"></i> <span class="nav-label">授权管理</span><span class="fa arrow"></span></a>
|
<a href="#"><i class="fa fa-edit"></i> <span class="nav-label">{% trans 'Perms' %}</span><span class="fa arrow"></span></a>
|
||||||
<ul class="nav nav-second-level">
|
<ul class="nav nav-second-level">
|
||||||
<li class="sudo">
|
<li class="sudo">
|
||||||
<a class="sudo" href="">授权列表</a>
|
<a class="sudo" href="">{% trans 'Perm' %}</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="role">
|
<li class="role">
|
||||||
<a href="">添加授权</a>
|
<a href="">{% trans 'Create perm' %}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li id="">
|
<li id="">
|
||||||
<a href="">
|
<a href="">
|
||||||
<i class="fa fa-files-o"></i><span class="nav-label">审计管理</span><span class="label label-info pull-right"></span>
|
<i class="fa fa-files-o"></i><span class="nav-label">{% trans 'Audits' %}</span><span class="label label-info pull-right"></span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li id="">
|
<li id="">
|
||||||
<a href="#">
|
<a href="#">
|
||||||
<i class="fa fa-download"></i> <span class="nav-label">上传下载</span><span class="fa arrow"></span>
|
<i class="fa fa-download"></i> <span class="nav-label">{% trans 'File' %}</span><span class="fa arrow"></span>
|
||||||
</a>
|
</a>
|
||||||
<ul class="nav nav-second-level">
|
<ul class="nav nav-second-level">
|
||||||
<li class="upload"><a href="">文件上传</a></li>
|
<li class="upload"><a href="">{% trans 'File upload' %}</a></li>
|
||||||
<li class="download"><a href="">文件下载</a></li>
|
<li class="download"><a href="">{% trans 'File download' %}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li id="">
|
<li id="">
|
||||||
<a href="">
|
<a href="">
|
||||||
<i class="fa fa-gears"></i> <span class="nav-label">设置</span><span class="label label-info pull-right"></span>
|
<i class="fa fa-gears"></i> <span class="nav-label">{% trans 'Settings' %}</span><span class="label label-info pull-right"></span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="special_link">
|
<li class="special_link">
|
||||||
<a href="http://www.jumpserver.org" target="_blank"><i class="fa fa-database"></i>
|
<a href="http://www.jumpserver.org" target="_blank"><i class="fa fa-database"></i>
|
||||||
<span class="nav-label">访问官网</span>
|
<span class="nav-label">{% trans 'Visit us' %}</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
|
@ -34,10 +34,10 @@
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<script>
|
<script>
|
||||||
function sleep(n) { //n表示的毫秒数
|
{# function sleep(n) { //n表示的毫秒数#}
|
||||||
var start = new Date().getTime();
|
{# var start = new Date().getTime();#}
|
||||||
while (true) if (new Date().getTime() - start > n) break;
|
{# while (true) if (new Date().getTime() - start > n) break;#}
|
||||||
}
|
{# }#}
|
||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$('.page').click(function () {
|
$('.page').click(function () {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
{% load i18n %}
|
||||||
<li class="nav-header">
|
<li class="nav-header">
|
||||||
<div class="dropdown profile-element">
|
<div class="dropdown profile-element">
|
||||||
<span>
|
<span>
|
||||||
|
@ -10,15 +11,14 @@
|
||||||
<strong class="font-bold"> {{ request.user.name }}<span style="color: #8095a8"></span></strong>
|
<strong class="font-bold"> {{ request.user.name }}<span style="color: #8095a8"></span></strong>
|
||||||
</span>
|
</span>
|
||||||
<span class="text-muted text-xs block">
|
<span class="text-muted text-xs block">
|
||||||
{{ request.user.get_role_display | default:'普通用户' }}<b class="caret"></b>
|
{{ request.user.get_role_display | default:"{% trans 'User' %}" }}<b class="caret"></b>
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</a>
|
</a>
|
||||||
<ul class="dropdown-menu animated fadeInRight m-t-xs">
|
<ul class="dropdown-menu animated fadeInRight m-t-xs">
|
||||||
<li><a value="">个人信息</a></li>
|
<li><a value="">{% trans 'Profile' %}</a></li>
|
||||||
<li><a href="">修改信息</a></li>
|
|
||||||
<li class="divider"></li>
|
<li class="divider"></li>
|
||||||
<li><a href="">注销</a></li>
|
<li><a href="">{% trans 'Logout' %}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="logo-element">
|
<div class="logo-element">
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<meta name="renderer" content="webkit">
|
<meta name="renderer" content="webkit">
|
||||||
|
|
||||||
<title>Jumpserver | 开源跳板机系统</title>
|
<title>Jumpserver</title>
|
||||||
|
|
||||||
<link rel="shortcut icon" href={% static "img/facio.ico" %} type="image/x-icon">
|
<link rel="shortcut icon" href={% static "img/facio.ico" %} type="image/x-icon">
|
||||||
{% include '_head_css_js.html' %}
|
{% include '_head_css_js.html' %}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
{{image}}{{hidden_field}}{{text_field}}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function refresh_captcha() {
|
||||||
|
$.getJSON("{% url "captcha-refresh" %}",
|
||||||
|
function (result) {
|
||||||
|
$('.captcha').attr('src', result['image_url']);
|
||||||
|
$('#id_captcha_0').val(result['key'])
|
||||||
|
})
|
||||||
|
}
|
||||||
|
$('.captcha').click(refresh_captcha)
|
||||||
|
</script>
|
|
@ -0,0 +1 @@
|
||||||
|
<input id="{{id}}_0" name="{{name}}_0" type="hidden" value="{{key}}" />
|
|
@ -0,0 +1,4 @@
|
||||||
|
{% load i18n %}
|
||||||
|
{% spaceless %}
|
||||||
|
{% if audio %}<a title="{% trans "Play CAPTCHA as audio file" %}" href="{{audio}}">{% endif %}<img src="{{image}}" alt="captcha" class="captcha" />{% if audio %}</a>{% endif %}
|
||||||
|
{% endspaceless %}
|
|
@ -0,0 +1,7 @@
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<input autocomplete="off" id="{{id}}_1" class="form-control" name="{{name}}_1" type="text" />
|
||||||
|
<span class="red-fonts" id="captcha-error" style="display: none">验证码错误</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</br>
|
|
@ -2,21 +2,16 @@
|
||||||
|
|
||||||
from django.forms import ModelForm
|
from django.forms import ModelForm
|
||||||
from django import forms
|
from django import forms
|
||||||
|
from captcha.fields import CaptchaField
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from .models import User, UserGroup
|
from .models import User, UserGroup
|
||||||
|
|
||||||
|
|
||||||
# class UserLoginForm(ModelForm):
|
|
||||||
# class Meta:
|
|
||||||
# model = User
|
|
||||||
# fields = [
|
|
||||||
# "email", "password"
|
|
||||||
# ]
|
|
||||||
|
|
||||||
|
|
||||||
class UserLoginForm(forms.Form):
|
class UserLoginForm(forms.Form):
|
||||||
username = forms.CharField(label='用户名', max_length=100)
|
username = forms.CharField(label=_('Username'), max_length=100)
|
||||||
password = forms.CharField(label='密码', widget=forms.PasswordInput, max_length=100)
|
password = forms.CharField(label=_('Password'), widget=forms.PasswordInput, max_length=100)
|
||||||
|
captcha = CaptchaField()
|
||||||
|
|
||||||
|
|
||||||
class UserAddForm(ModelForm):
|
class UserAddForm(ModelForm):
|
||||||
|
@ -33,7 +28,7 @@ class UserAddForm(ModelForm):
|
||||||
}
|
}
|
||||||
|
|
||||||
widgets = {
|
widgets = {
|
||||||
'groups': forms.SelectMultiple(attrs={'class': 'select2', 'data-placeholder': '请选择用户组'}),
|
'groups': forms.SelectMultiple(attrs={'class': 'select2', 'data-placeholder': _('Join usergroups')}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,7 +47,7 @@ class UserUpdateForm(ModelForm):
|
||||||
}
|
}
|
||||||
|
|
||||||
widgets = {
|
widgets = {
|
||||||
'groups': forms.SelectMultiple(attrs={'class': 'select2', 'data-placeholder': '请选择用户组'}),
|
'groups': forms.SelectMultiple(attrs={'class': 'select2', 'data-placeholder': _('Join usergroups')}),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,379 @@
|
||||||
|
# SOME DESCRIPTIVE TITLE.
|
||||||
|
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||||
|
# This file is distributed under the same license as the PACKAGE package.
|
||||||
|
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: \n"
|
||||||
|
"POT-Creation-Date: 2016-09-04 17:31+0800\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: users/forms.py:12 users/models.py:106 users/templates/users/login.html:57
|
||||||
|
#: users/templates/users/user_detail.html:73
|
||||||
|
#: users/templates/users/user_edit.html:5
|
||||||
|
#: users/templates/users/user_list.html:13
|
||||||
|
msgid "Username"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/forms.py:13 users/templates/users/login.html:60
|
||||||
|
#: users/templates/users/reset_password.html:52
|
||||||
|
#: users/templates/users/user_add.html:8 users/templates/users/user_add.html:10
|
||||||
|
#: users/templates/users/user_edit.html:12
|
||||||
|
#: users/templates/users/user_edit.html:14
|
||||||
|
msgid "Password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/forms.py:31 users/forms.py:50
|
||||||
|
msgid "Join usergroups"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/models.py:60 users/models.py:107
|
||||||
|
#: users/templates/users/user_detail.html:69
|
||||||
|
#: users/templates/users/user_list.html:12
|
||||||
|
msgid "Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/models.py:61 users/models.py:118
|
||||||
|
#: users/templates/users/user_detail.html:113
|
||||||
|
msgid "Comment"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/models.py:102 users/models.py:225
|
||||||
|
msgid "Administrator"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/models.py:103
|
||||||
|
msgid "User"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/models.py:108 users/templates/users/user_detail.html:77
|
||||||
|
msgid "Email"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/models.py:109 users/templates/users/user_detail.html:181
|
||||||
|
#: users/templates/users/user_list.html:15
|
||||||
|
msgid "Usergroup"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/models.py:110 users/templates/users/user_detail.html:93
|
||||||
|
#: users/templates/users/user_list.html:14
|
||||||
|
msgid "Role"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/models.py:111
|
||||||
|
msgid "Avatar"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/models.py:112 users/templates/users/user_detail.html:88
|
||||||
|
msgid "Wechat"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/models.py:113 users/templates/users/user_detail.html:82
|
||||||
|
msgid "Phone"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/models.py:114 users/templates/users/_user.html:56
|
||||||
|
msgid "Enable OTP"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/models.py:116
|
||||||
|
msgid "ssh private key"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/models.py:117
|
||||||
|
msgid "ssh public key"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/models.py:121 users/templates/users/user_detail.html:97
|
||||||
|
msgid "Date expired"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/models.py:122 users/templates/users/user_detail.html:101
|
||||||
|
msgid "Created by"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/models.py:228
|
||||||
|
msgid "Administrator is the super user of system"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/models.py:229
|
||||||
|
msgid "System"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/_user.html:17 users/templates/users/user_list.html:5
|
||||||
|
#: users/views.py:113
|
||||||
|
msgid "Create user"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/_user.html:33
|
||||||
|
msgid "Account"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/_user.html:43
|
||||||
|
msgid "Security and Role"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/_user.html:62
|
||||||
|
msgid "Profile"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/_user.html:69
|
||||||
|
#: users/templates/users/user_detail.html:162
|
||||||
|
#: users/templates/users/user_detail.html:170
|
||||||
|
msgid "Reset"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/_user.html:70
|
||||||
|
#: users/templates/users/forget_password.html:44
|
||||||
|
#: users/templates/users/user_list.html:63
|
||||||
|
msgid "Commit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/forget_password.html:26
|
||||||
|
msgid "Forget password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/forget_password.html:33
|
||||||
|
msgid "Input your email, that will send a mail to your"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/login.html:45 users/templates/users/login.html:65
|
||||||
|
msgid "Login"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/login.html:50
|
||||||
|
msgid "Captcha invalid"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/reset_password.html:45
|
||||||
|
#: users/templates/users/user_detail.html:159 users/utils.py:98
|
||||||
|
msgid "Reset password"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/reset_password.html:55
|
||||||
|
msgid "Password again"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/reset_password.html:57
|
||||||
|
msgid "Setting"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/user_add.html:12
|
||||||
|
msgid "Reset link will be generated and sent to the user. "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/user_delete_confirm.html:6
|
||||||
|
msgid "Confirm delete"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/user_detail.html:18 users/views.py:173
|
||||||
|
msgid "User detail"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/user_detail.html:20
|
||||||
|
msgid "User assets"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/user_detail.html:21
|
||||||
|
msgid "User log"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/user_detail.html:29
|
||||||
|
msgid "Search"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/user_detail.html:105
|
||||||
|
msgid "Date joined"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/user_detail.html:109
|
||||||
|
msgid "Last login"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/user_detail.html:124
|
||||||
|
msgid "Quick modify"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/user_detail.html:167
|
||||||
|
msgid "Reset ssh key"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/user_detail.html:189
|
||||||
|
msgid "Select usergroups"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/user_detail.html:198
|
||||||
|
msgid "Add"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/user_list.html:16
|
||||||
|
msgid "Asset num"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/user_list.html:17
|
||||||
|
msgid "Active"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/user_list.html:44
|
||||||
|
msgid "Edit"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/user_list.html:45
|
||||||
|
msgid "Delete"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/user_list.html:55
|
||||||
|
msgid "Delete selected"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/user_list.html:56
|
||||||
|
msgid "Update selected"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/user_list.html:57
|
||||||
|
msgid "Deactive selected"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/templates/users/user_list.html:58
|
||||||
|
msgid "Export selected"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/utils.py:47
|
||||||
|
msgid "Begin to generate ssh private key ..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/utils.py:59
|
||||||
|
msgid "Finish to generate ssh private key ..."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/utils.py:63
|
||||||
|
msgid "These is error when generate ssh key."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/utils.py:67
|
||||||
|
msgid "Create account successfully"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/utils.py:69
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"\n"
|
||||||
|
" Hello %(name)s:\n"
|
||||||
|
" </br>\n"
|
||||||
|
" Your account has been created successfully\n"
|
||||||
|
" </br>\n"
|
||||||
|
" <a href=\"%(rest_password_url)s?token=%(rest_password_token)s\">click "
|
||||||
|
"here to set your password</a>\n"
|
||||||
|
" </br>\n"
|
||||||
|
" This link is valid for 1 hour. After it expires, <a href="
|
||||||
|
"\"%(forget_password_url)s?email=%(email)s\">request new one</a>\n"
|
||||||
|
"\n"
|
||||||
|
" </br>\n"
|
||||||
|
" ---\n"
|
||||||
|
"\n"
|
||||||
|
" </br>\n"
|
||||||
|
" <a href=\"%(login_url)s\">Login direct</a>\n"
|
||||||
|
"\n"
|
||||||
|
" </br>\n"
|
||||||
|
" "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/utils.py:100
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"\n"
|
||||||
|
" Hello %(name)s:\n"
|
||||||
|
" </br>\n"
|
||||||
|
" Please click the link below to reset your password, if not your request, "
|
||||||
|
"concern your account security\n"
|
||||||
|
" </br>\n"
|
||||||
|
" <a href=\"%(rest_password_url)s?token=%(rest_password_token)s\">Click "
|
||||||
|
"here reset password</a>\n"
|
||||||
|
" </br>\n"
|
||||||
|
" This link is valid for 1 hour. After it expires, <a href="
|
||||||
|
"\"%(forget_password_url)s?email=%(email)s\">request new one<</a>\n"
|
||||||
|
"\n"
|
||||||
|
" </br>\n"
|
||||||
|
" ---\n"
|
||||||
|
"\n"
|
||||||
|
" </br>\n"
|
||||||
|
" <a href=\"%(login_url)s\">Login direct</a>\n"
|
||||||
|
"\n"
|
||||||
|
" </br>\n"
|
||||||
|
" "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/views.py:53
|
||||||
|
msgid "Username or password invalid"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/views.py:70
|
||||||
|
msgid "Logout success"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/views.py:71
|
||||||
|
msgid "Logout success, return login page"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/views.py:100 users/views.py:113 users/views.py:155 users/views.py:173
|
||||||
|
#: users/views.py:197 users/views.py:210
|
||||||
|
msgid "Users"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/views.py:100
|
||||||
|
msgid "User list"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/views.py:109
|
||||||
|
#, python-format
|
||||||
|
msgid "Create user<a href=\"%s\">%s</a> success."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/views.py:155
|
||||||
|
msgid "Edit user"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/views.py:197
|
||||||
|
msgid "Usergroup list"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/views.py:210
|
||||||
|
msgid "Create usergroup"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/views.py:242
|
||||||
|
msgid "Email address invalid, input again"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/views.py:253
|
||||||
|
msgid "Send reset password message"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/views.py:254
|
||||||
|
msgid "Send reset password mail success, login your mail box and follow it "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/views.py:266
|
||||||
|
msgid "Reset password success"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/views.py:267
|
||||||
|
msgid "Reset password success, return to login page"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/views.py:283 users/views.py:296
|
||||||
|
msgid "Token invalid or expired"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: users/views.py:292
|
||||||
|
msgid "Password not same"
|
||||||
|
msgstr ""
|
|
@ -12,6 +12,7 @@ from django.contrib.auth.models import AbstractUser, Permission
|
||||||
from django.db.models.signals import post_save
|
from django.db.models.signals import post_save
|
||||||
from django.dispatch import receiver
|
from django.dispatch import receiver
|
||||||
from django.db import IntegrityError
|
from django.db import IntegrityError
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from rest_framework.authtoken.models import Token
|
from rest_framework.authtoken.models import Token
|
||||||
|
|
||||||
from django.core import signing
|
from django.core import signing
|
||||||
|
@ -56,8 +57,8 @@ from django.core import signing
|
||||||
|
|
||||||
|
|
||||||
class UserGroup(models.Model):
|
class UserGroup(models.Model):
|
||||||
name = models.CharField(max_length=100, unique=True, verbose_name='组名称')
|
name = models.CharField(max_length=100, unique=True, verbose_name=_('Name'))
|
||||||
comment = models.TextField(blank=True, verbose_name='描述')
|
comment = models.TextField(blank=True, verbose_name=_('Comment'))
|
||||||
date_added = models.DateTimeField(auto_now_add=True)
|
date_added = models.DateTimeField(auto_now_add=True)
|
||||||
created_by = models.CharField(max_length=100)
|
created_by = models.CharField(max_length=100)
|
||||||
|
|
||||||
|
@ -98,26 +99,27 @@ def date_expired_default():
|
||||||
|
|
||||||
class User(AbstractUser):
|
class User(AbstractUser):
|
||||||
ROLE_CHOICES = (
|
ROLE_CHOICES = (
|
||||||
('Admin', '管理员'),
|
('Admin', _('Administrator')),
|
||||||
('User', '用户'),
|
('User', _('User')),
|
||||||
)
|
)
|
||||||
|
|
||||||
username = models.CharField(max_length=20, unique=True, verbose_name='用户名')
|
username = models.CharField(max_length=20, unique=True, verbose_name=_('Username'))
|
||||||
name = models.CharField(max_length=20, blank=True, verbose_name='姓名')
|
name = models.CharField(max_length=20, blank=True, verbose_name=_('Name'))
|
||||||
email = models.EmailField(max_length=30, unique=True, verbose_name='邮件')
|
email = models.EmailField(max_length=30, unique=True, verbose_name=_('Email'))
|
||||||
groups = models.ManyToManyField(UserGroup, related_name='users', blank=True, verbose_name='用户组')
|
groups = models.ManyToManyField(UserGroup, related_name='users', blank=True, verbose_name=_('Usergroup'))
|
||||||
role = models.CharField(choices=ROLE_CHOICES, default='User', max_length=10, blank=True, verbose_name='角色')
|
role = models.CharField(choices=ROLE_CHOICES, default='User', max_length=10, blank=True, verbose_name=_('Role'))
|
||||||
avatar = models.ImageField(upload_to="avatar", verbose_name='头像')
|
avatar = models.ImageField(upload_to="avatar", verbose_name=_('Avatar'))
|
||||||
wechat = models.CharField(max_length=30, blank=True, verbose_name='微信')
|
wechat = models.CharField(max_length=30, blank=True, verbose_name=_('Wechat'))
|
||||||
phone = models.CharField(max_length=20, blank=True, verbose_name='手机号')
|
phone = models.CharField(max_length=20, blank=True, verbose_name=_('Phone'))
|
||||||
enable_otp = models.BooleanField(default=False, verbose_name='启用二次验证')
|
enable_otp = models.BooleanField(default=False, verbose_name=_('Enable OTP'))
|
||||||
secret_key_otp = models.CharField(max_length=16, blank=True)
|
secret_key_otp = models.CharField(max_length=16, blank=True)
|
||||||
private_key = models.CharField(max_length=5000, blank=True, verbose_name='ssh私钥') # ssh key max length 4096 bit
|
private_key = models.CharField(max_length=5000, blank=True, verbose_name=_('ssh private key'))
|
||||||
public_key = models.CharField(max_length=1000, blank=True, verbose_name='公钥')
|
public_key = models.CharField(max_length=1000, blank=True, verbose_name=_('ssh public key'))
|
||||||
comment = models.TextField(max_length=200, blank=True, verbose_name='描述')
|
comment = models.TextField(max_length=200, blank=True, verbose_name=_('Comment'))
|
||||||
is_first_login = models.BooleanField(default=False)
|
is_first_login = models.BooleanField(default=False)
|
||||||
date_expired = models.DateTimeField(default=date_expired_default, blank=True, null=True, verbose_name='有效期')
|
date_expired = models.DateTimeField(default=date_expired_default, blank=True, null=True,
|
||||||
created_by = models.CharField(max_length=30, default='')
|
verbose_name=_('Date expired'))
|
||||||
|
created_by = models.CharField(max_length=30, default='', verbose_name=_('Created by'))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def password_raw(self):
|
def password_raw(self):
|
||||||
|
@ -204,7 +206,7 @@ class User(AbstractUser):
|
||||||
user_email = data.get('email', '')
|
user_email = data.get('email', '')
|
||||||
user = cls.objects.get(id=user_id, email=user_email)
|
user = cls.objects.get(id=user_id, email=user_email)
|
||||||
|
|
||||||
except signing.BadSignature, cls.DoesNotExist:
|
except (signing.BadSignature, cls.DoesNotExist):
|
||||||
user = None
|
user = None
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
@ -220,11 +222,11 @@ class User(AbstractUser):
|
||||||
def initial(cls):
|
def initial(cls):
|
||||||
user = cls(username='admin',
|
user = cls(username='admin',
|
||||||
email='admin@jumpserver.org',
|
email='admin@jumpserver.org',
|
||||||
name='Administrator',
|
name=_('Administrator'),
|
||||||
password_raw='admin',
|
password_raw='admin',
|
||||||
role='Admin',
|
role='Admin',
|
||||||
comment='Administrator is the super user of system',
|
comment=_('Administrator is the super user of system'),
|
||||||
created_by='System')
|
created_by=_('System'))
|
||||||
user.save()
|
user.save()
|
||||||
user.groups.add(UserGroup.initial())
|
user.groups.add(UserGroup.initial())
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
{% load bootstrap %}
|
{% load bootstrap %}
|
||||||
{% block custom_head_css_js %}
|
{% block custom_head_css_js %}
|
||||||
|
@ -13,7 +14,7 @@
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<div class="ibox float-e-margins">
|
<div class="ibox float-e-margins">
|
||||||
<div class="ibox-title">
|
<div class="ibox-title">
|
||||||
<h5>填写用户信息</h5>
|
<h5>{% trans 'Create user' %}</h5>
|
||||||
<div class="ibox-tools">
|
<div class="ibox-tools">
|
||||||
<a class="collapse-link">
|
<a class="collapse-link">
|
||||||
<i class="fa fa-chevron-up"></i>
|
<i class="fa fa-chevron-up"></i>
|
||||||
|
@ -29,7 +30,7 @@
|
||||||
<div class="ibox-content">
|
<div class="ibox-content">
|
||||||
<form method="post" id="userForm" class="form-horizontal" action="" enctype="multipart/form-data">
|
<form method="post" id="userForm" class="form-horizontal" action="" enctype="multipart/form-data">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
<h3>账户</h3>
|
<h3>{% trans 'Account' %}</h3>
|
||||||
{% block username %} {% endblock %}
|
{% block username %} {% endblock %}
|
||||||
{{ form.email|bootstrap_horizontal }}
|
{{ form.email|bootstrap_horizontal }}
|
||||||
{{ form.name|bootstrap_horizontal }}
|
{{ form.name|bootstrap_horizontal }}
|
||||||
|
@ -39,7 +40,7 @@
|
||||||
{% block password %} {% endblock %}
|
{% block password %} {% endblock %}
|
||||||
|
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
<h3>角色安全</h3>
|
<h3>{% trans 'Security and Role' %}</h3>
|
||||||
{{ form.role|bootstrap_horizontal }}
|
{{ form.role|bootstrap_horizontal }}
|
||||||
<div class="form-group {% if form.date_expired.errors %} has-error {% endif %}" id="date_5">
|
<div class="form-group {% if form.date_expired.errors %} has-error {% endif %}" id="date_5">
|
||||||
<label for="{{ form.date_expired.id_for_label }}" class="col-sm-2 control-label">{{ form.date_expired.label }}</label>
|
<label for="{{ form.date_expired.id_for_label }}" class="col-sm-2 control-label">{{ form.date_expired.label }}</label>
|
||||||
|
@ -52,21 +53,21 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="{{ form.enable_otp.id_for_label }}" class="col-sm-2 control-label">二次验证</label>
|
<label for="{{ form.enable_otp.id_for_label }}" class="col-sm-2 control-label">{% trans 'Enable OTP' %}</label>
|
||||||
<div class="col-sm-8">
|
<div class="col-sm-8">
|
||||||
{{ form.enable_otp }}
|
{{ form.enable_otp }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
<h3>信息</h3>
|
<h3>{% trans 'Profile' %}</h3>
|
||||||
{{ form.phone|bootstrap_horizontal }}
|
{{ form.phone|bootstrap_horizontal }}
|
||||||
{{ form.wechat|bootstrap_horizontal }}
|
{{ form.wechat|bootstrap_horizontal }}
|
||||||
{{ form.comment|bootstrap_horizontal }}
|
{{ form.comment|bootstrap_horizontal }}
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-sm-4 col-sm-offset-2">
|
<div class="col-sm-4 col-sm-offset-2">
|
||||||
<button class="btn btn-white" type="reset">取消</button>
|
<button class="btn btn-white" type="reset">{% trans 'Reset' %}</button>
|
||||||
<button id="submit_button" class="btn btn-primary" type="submit">确认保存</button>
|
<button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Commit' %}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
{% load i18n %}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
|
@ -6,8 +7,8 @@
|
||||||
|
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<link rel="shortcut icon" href="{% static "img/facio.ico" %}" type="image/x-icon">
|
||||||
<title>INSPINIA | Forgot password</title>
|
<title>忘记密码</title>
|
||||||
|
|
||||||
{% include '_head_css_js.html' %}
|
{% include '_head_css_js.html' %}
|
||||||
<link href="{% static "css/jumpserver.css" %}" rel="stylesheet">
|
<link href="{% static "css/jumpserver.css" %}" rel="stylesheet">
|
||||||
|
@ -22,14 +23,14 @@
|
||||||
<div class="ibox-content">
|
<div class="ibox-content">
|
||||||
|
|
||||||
<img src="{% static 'img/logo.png' %}" style="margin: auto" width="82" height="82">
|
<img src="{% static 'img/logo.png' %}" style="margin: auto" width="82" height="82">
|
||||||
<h2 class="font-bold" style="display: inline">忘记密码 ?</h2>
|
<h2 class="font-bold" style="display: inline">{% trans 'Forget password' %} ?</h2>
|
||||||
|
|
||||||
<h1></h1>
|
<h1></h1>
|
||||||
{% if errors %}
|
{% if errors %}
|
||||||
<p class="red-fonts">{{ errors }}</p>
|
<p class="red-fonts">{{ errors }}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<p>
|
<p>
|
||||||
输入您的邮箱, 将会发一封重置短信邮件到您的邮箱中
|
{% trans 'Input your email, that will send a mail to your' %}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -40,7 +41,7 @@
|
||||||
<input type="email" name="email" class="form-control" placeholder="Email address" required="">
|
<input type="email" name="email" class="form-control" placeholder="Email address" required="">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button type="submit" class="btn btn-primary block full-width m-b">重置密码</button>
|
<button type="submit" class="btn btn-primary block full-width m-b">{% trans 'Commit' %}</button>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
{% load i18n %}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
|
@ -10,28 +11,30 @@
|
||||||
{% include '_head_css_js.html' %}
|
{% include '_head_css_js.html' %}
|
||||||
<link href="{% static "css/jumpserver.css" %}" rel="stylesheet">
|
<link href="{% static "css/jumpserver.css" %}" rel="stylesheet">
|
||||||
<script src="{% static "js/jumpserver.js" %}"></script>
|
<script src="{% static "js/jumpserver.js" %}"></script>
|
||||||
|
<style>
|
||||||
|
.captcha {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
#id_captcha_1 {
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="gray-bg">
|
<body class="gray-bg">
|
||||||
<div class="loginColumns animated fadeInDown">
|
<div class="loginColumns animated fadeInDown">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
|
|
||||||
<h2 class="font-bold">欢迎使用Jumpserver开源跳板机</h2>
|
<h2 class="font-bold">欢迎使用Jumpserver开源跳板机</h2>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Jumpserver是一款使用Python, Django开发的开源跳板机系统, 助力互联网企业高效 用户、资产、权限、审计 管理
|
Jumpserver是一款使用Python, Django开发的开源跳板机系统, 助力互联网企业高效 用户、资产、权限、审计 管理
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
我们自五湖四海,我们对开源精神无比敬仰和崇拜,我们对完美、整洁、优雅 无止境的追求
|
我们自五湖四海,我们对开源精神无比敬仰和崇拜,我们对完美、整洁、优雅 无止境的追求
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
专注自动化运维,努力打造 易用、稳定、安全、自动化 的跳板机, 这是我们的不懈的追求和动力
|
专注自动化运维,努力打造 易用、稳定、安全、自动化 的跳板机, 这是我们的不懈的追求和动力
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
<small>永远年轻,永远热泪盈眶 stay foolish stay hungry</small>
|
<small>永远年轻,永远热泪盈眶 stay foolish stay hungry</small>
|
||||||
</p>
|
</p>
|
||||||
|
@ -39,31 +42,36 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="ibox-content">
|
<div class="ibox-content">
|
||||||
<div><img src="{% static 'img/logo.png' %}" width="82" height="82"> <span class="font-bold text-center" style="font-size: 32px; font-family: inherit">登录</span></div>
|
<div><img src="{% static 'img/logo.png' %}" width="82" height="82"> <span class="font-bold text-center" style="font-size: 32px; font-family: inherit">{% trans 'Login' %}</span></div>
|
||||||
<form class="m-t" role="form" method="post" action="{% url 'users:login' %}">
|
<form class="m-t" role="form" method="post" action="{% url 'users:login' %}">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{% if form.errors %}
|
{% if form.errors %}
|
||||||
<p class="red-fonts">用户名/密码 不正确, 请重试</p>
|
{% if 'captcha' in form.errors %}
|
||||||
|
<p class="red-fonts">{% trans 'Captcha invalid' %}</p>
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% if errors %}
|
||||||
|
<p class="red-fonts">{{ errors }}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="text" class="form-control" name="username" placeholder="Username" required="">
|
<input type="text" class="form-control" name="{{ form.username.html_name }}" placeholder="{% trans 'Username' %}" required="">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="password" class="form-control" name="password" placeholder="Password" required="">
|
<input type="password" class="form-control" name="{{ form.password.html_name }}" placeholder="{% trans 'Password' %}" required="">
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-primary block full-width m-b">Login</button>
|
<div>
|
||||||
|
{{ form.captcha }}
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary block full-width m-b">{% trans 'Login' %}</button>
|
||||||
|
|
||||||
<a href="{% url 'users:forget-password' %}">
|
<a href="{% url 'users:forget-password' %}">
|
||||||
<small>Forgot password?</small>
|
<small>Forgot password?</small>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<p class="text-muted text-center">
|
<p class="text-muted text-center">
|
||||||
{# <small>Do not have an account?</small>#}
|
|
||||||
</p>
|
</p>
|
||||||
{# <a class="btn btn-sm btn-white btn-block" href="register.html">Create an account</a>#}
|
|
||||||
</form>
|
</form>
|
||||||
<p class="m-t">
|
<p class="m-t">
|
||||||
{# <small>Inspinia we app framework base on Bootstrap 3 © 2014</small>#}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -78,7 +86,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
{% load i18n %}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
|
@ -41,31 +42,28 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div class="ibox-content">
|
<div class="ibox-content">
|
||||||
<div><img src="{% static 'img/logo.png' %}" width="82" height="82"> <span class="font-bold text-center" style="font-size: 32px; font-family: inherit">重设密码</span></div>
|
<div><img src="{% static 'img/logo.png' %}" width="82" height="82"> <span class="font-bold text-center" style="font-size: 32px; font-family: inherit">{% trans 'Reset password' %}</span></div>
|
||||||
<form class="m-t" role="form" method="post" action="">
|
<form class="m-t" role="form" method="post" action="">
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{% if errors %}
|
{% if errors %}
|
||||||
<p class="red-fonts">{{ errors }}</p>
|
<p class="red-fonts">{{ errors }}</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="password" class="form-control" name="password" placeholder="Password" required="">
|
<input type="password" class="form-control" name="password" placeholder="{% trans 'Password' %}" required="">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="password" class="form-control" name="password-confirm" placeholder="Password again" required="">
|
<input type="password" class="form-control" name="password-confirm" placeholder="{% trans 'Password again' %}" required="">
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-primary block full-width m-b">Setting</button>
|
<button type="submit" class="btn btn-primary block full-width m-b">{% trans "Setting" %}</button>
|
||||||
|
|
||||||
<a href="#">
|
<a href="#">
|
||||||
<small>Forgot password?</small>
|
<small>Forgot password?</small>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<p class="text-muted text-center">
|
<p class="text-muted text-center">
|
||||||
{# <small>Do not have an account?</small>#}
|
|
||||||
</p>
|
</p>
|
||||||
{# <a class="btn btn-sm btn-white btn-block" href="register.html">Create an account</a>#}
|
|
||||||
</form>
|
</form>
|
||||||
<p class="m-t">
|
<p class="m-t">
|
||||||
{# <small>Inspinia we app framework base on Bootstrap 3 © 2014</small>#}
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
{% extends 'users/_user.html' %}
|
{% extends 'users/_user.html' %}
|
||||||
|
{% load i18n %}
|
||||||
{% load bootstrap %}
|
{% load bootstrap %}
|
||||||
{% block username %}
|
{% block username %}
|
||||||
{{ form.username|bootstrap_horizontal }}
|
{{ form.username|bootstrap_horizontal }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block password %}
|
{% block password %}
|
||||||
<h3>密码</h3>
|
<h3>{% trans 'Password' %}</h3>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-2 control-label">密码</label>
|
<label class="col-sm-2 control-label">{% trans 'Password' %}</label>
|
||||||
<div class="col-sm-8 controls" >
|
<div class="col-sm-8 controls" >
|
||||||
生成重置密码连接,通过邮件发送给用户
|
{% trans 'Reset link will be generated and sent to the user. ' %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -1,8 +1,9 @@
|
||||||
|
{% load i18n %}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>确认删除</title>
|
<title>{% trans 'Confirm delete' %}</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<form action="" method="post">
|
<form action="" method="post">
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
{% load common_tags %}
|
{% load common_tags %}
|
||||||
{% load users_tags %}
|
{% load users_tags %}
|
||||||
{% load static %}
|
{% load static %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
{% block custom_head_css_js %}
|
{% block custom_head_css_js %}
|
||||||
<link href="{% static "css/plugins/select2/select2.min.css" %}" rel="stylesheet">
|
<link href="{% static "css/plugins/select2/select2.min.css" %}" rel="stylesheet">
|
||||||
|
@ -12,13 +13,12 @@
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
<div class="ibox float-e-margins">
|
<div class="ibox float-e-margins">
|
||||||
{# <div class="ibox-content">#}
|
|
||||||
<div class="panel-options">
|
<div class="panel-options">
|
||||||
<ul class="nav nav-tabs">
|
<ul class="nav nav-tabs">
|
||||||
<li class="active"><a href="" class="text-center"><i class="fa fa-laptop"></i> 用户信息 </a>
|
<li class="active"><a href="" class="text-center"><i class="fa fa-laptop"></i> {% trans 'User detail' %} </a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="" class="text-center"><i class="fa fa-bar-chart-o"></i> 用户资产</a></li>
|
<li><a href="" class="text-center"><i class="fa fa-bar-chart-o"></i> {% trans 'User assets' %}</a></li>
|
||||||
<li><a href="" class="text-center"><i class="fa fa-bar-chart-o"></i> 登录记录 </a></li>
|
<li><a href="" class="text-center"><i class="fa fa-bar-chart-o"></i> {% trans 'User log' %}</a></li>
|
||||||
<div class="" style="float: right">
|
<div class="" style="float: right">
|
||||||
<form id="search_form" method="get" action="" class="pull-right mail-search">
|
<form id="search_form" method="get" action="" class="pull-right mail-search">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
|
@ -26,7 +26,7 @@
|
||||||
value="{{ keyword }}" placeholder="Search">
|
value="{{ keyword }}" placeholder="Search">
|
||||||
<div class="input-group-btn">
|
<div class="input-group-btn">
|
||||||
<button id='search_btn' type="submit" class="btn btn-sm btn-primary">
|
<button id='search_btn' type="submit" class="btn btn-sm btn-primary">
|
||||||
搜索
|
{% trans 'Search' %}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -66,52 +66,52 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="20%">姓名:</td>
|
<td width="20%">{% trans 'Name' %}:</td>
|
||||||
<td><b>{{ user.name }}</b></td>
|
<td><b>{{ user.name }}</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>用户名:</td>
|
<td>{% trans 'Username' %}:</td>
|
||||||
<td><b>{{ user.username }}</b></td>
|
<td><b>{{ user.username }}</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>邮件:</td>
|
<td>{% trans 'Email' %}:</td>
|
||||||
<td><b>{{ user.email }}</b></td>
|
<td><b>{{ user.email }}</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% if user.phone %}
|
{% if user.phone %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>手机:</td>
|
<td>{% trans 'Phone' %}:</td>
|
||||||
<td><b>{{ user.phone }}</b></td>
|
<td><b>{{ user.phone }}</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if user.wechat %}
|
{% if user.wechat %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>微信:</td>
|
<td>{% trans 'Wechat' %}:</td>
|
||||||
<td><b>{{ user.wechat }}</b></td>
|
<td><b>{{ user.wechat }}</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>角色:</td>
|
<td>{% trans 'Role' %}:</td>
|
||||||
<td><b>{{ user.get_role_display }}</b></td>
|
<td><b>{{ user.get_role_display }}</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>有效期:</td>
|
<td>{% trans 'Date expired' %}:</td>
|
||||||
<td><b>{{ user.date_expired|date:"Y-m-j H:i:s" }}</b></td>
|
<td><b>{{ user.date_expired|date:"Y-m-j H:i:s" }}</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>创建者:</td>
|
<td>{% trans 'Created by' %}:</td>
|
||||||
<td><b>{{ user.created_by }}</b></td>
|
<td><b>{{ user.created_by }}</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>创建日期:</td>
|
<td>{% trans 'Date joined' %}:</td>
|
||||||
<td><b>{{ user.date_joined|date:"Y-m-j H:i:s" }}</b></td>
|
<td><b>{{ user.date_joined|date:"Y-m-j H:i:s" }}</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>最后登录:</td>
|
<td>{% trans 'Last login' %}:</td>
|
||||||
<td><b>{{ user.last_login|date:"Y-m-j H:i:s" }}</b></td>
|
<td><b>{{ user.last_login|date:"Y-m-j H:i:s" }}</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="no-borders">描述:</td>
|
<td>{% trans 'Comment' %}:</td>
|
||||||
<td class="no-borders"><b>{{ user.comment }}</b></td>
|
<td><b>{{ user.comment }}</b></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
@ -121,7 +121,7 @@
|
||||||
<div class="col-sm-5" style="padding-left: 0px;">
|
<div class="col-sm-5" style="padding-left: 0px;">
|
||||||
<div class="panel panel-primary">
|
<div class="panel panel-primary">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<i class="fa fa-info-circle"></i> 快速修改
|
<i class="fa fa-info-circle"></i> {% trans 'Quick modify' %}
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<table class="table">
|
<table class="table">
|
||||||
|
@ -156,18 +156,18 @@
|
||||||
</span></td>
|
</span></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>重置密码:</td>
|
<td>{% trans 'Reset password' %}:</td>
|
||||||
<td>
|
<td>
|
||||||
<span style="float: right">
|
<span style="float: right">
|
||||||
<button type="button" class="btn btn-primary btn-xs" style="width: 54px">重置</button>
|
<button type="button" class="btn btn-primary btn-xs" style="width: 54px">{% trans 'Reset' %}</button>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>重置密钥:</td>
|
<td>{% trans 'Reset ssh key' %}:</td>
|
||||||
<td>
|
<td>
|
||||||
<span style="float: right">
|
<span style="float: right">
|
||||||
<button type="button" class="btn btn-primary btn-xs" style="width: 54px;">重置</button>
|
<button type="button" class="btn btn-primary btn-xs" style="width: 54px;">{% trans 'Reset' %}</button>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -178,7 +178,7 @@
|
||||||
|
|
||||||
<div class="panel panel-info">
|
<div class="panel panel-info">
|
||||||
<div class="panel-heading">
|
<div class="panel-heading">
|
||||||
<i class="fa fa-info-circle"></i> 用户组
|
<i class="fa fa-info-circle"></i> {% trans 'Usergroup' %}
|
||||||
</div>
|
</div>
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
<table class="table">
|
<table class="table">
|
||||||
|
@ -186,7 +186,7 @@
|
||||||
<form>
|
<form>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2" class="no-borders">
|
<td colspan="2" class="no-borders">
|
||||||
<select data-placeholder="选择用户组" class="select2" style="width: 100%" multiple="" tabindex="4">
|
<select data-placeholder="{% trans 'Select usergroups' %}" class="select2" style="width: 100%" multiple="" tabindex="4">
|
||||||
{% for group in groups %}
|
{% for group in groups %}
|
||||||
<option value="{{ group.id }}">{{ group.name }}</option>
|
<option value="{{ group.id }}">{{ group.name }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -195,7 +195,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="2" class="no-borders">
|
<td colspan="2" class="no-borders">
|
||||||
<button type="button" class="btn btn-info btn-small">添加到用户组</button>
|
<button type="button" class="btn btn-info btn-small">{% trans 'Add' %}</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
{% extends 'users/_user.html' %}
|
{% extends 'users/_user.html' %}
|
||||||
|
{% load i18n %}
|
||||||
{% block username %}
|
{% block username %}
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="{{ form.username.id_for_label }}" class="col-sm-2 control-label">用户名</label>
|
<label for="{{ form.username.id_for_label }}" class="col-sm-2 control-label">{% trans 'Username' %}</label>
|
||||||
<div class="col-sm-9 controls" >
|
<div class="col-sm-9 controls" >
|
||||||
<input id="{{ form.username.id_for_label }}" name="{{ form.username.html_name }}" type="text" value="{{ user.username }}" readonly class="form-control">
|
<input id="{{ form.username.id_for_label }}" name="{{ form.username.html_name }}" type="text" value="{{ user.username }}" readonly class="form-control">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block password %}
|
{% block password %}
|
||||||
<h3>密码</h3>
|
<h3>{% trans 'Password' %}</h3>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="password" class="col-sm-2 control-label">密码</label>
|
<label for="password" class="col-sm-2 control-label">{% trans 'Password' %}</label>
|
||||||
<div class="col-sm-9 controls" >
|
<div class="col-sm-9 controls" >
|
||||||
<input id="password" name="password" type="password" class="form-control">
|
<input id="password" name="password" type="password" class="form-control">
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,92 +0,0 @@
|
||||||
{% extends '_list_base.html' %}
|
|
||||||
{% load common_tags %}
|
|
||||||
<div class="col-sm-12">
|
|
||||||
<div class="ibox float-e-margins">
|
|
||||||
<div class="ibox-title">
|
|
||||||
<h5> 查看用户 </h5>
|
|
||||||
<div class="ibox-tools">
|
|
||||||
<a class="collapise-link">
|
|
||||||
<i class="fa fa-chevron-up"></i>
|
|
||||||
</a>
|
|
||||||
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
|
|
||||||
<i class="fa fa-wrench"></i>
|
|
||||||
</a>
|
|
||||||
<a class="close-link">
|
|
||||||
<i class="fa fa-times"></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="ibox-content">
|
|
||||||
<div class="">
|
|
||||||
<a href="{% url 'users:user-add' %}" class="btn btn-sm btn-primary "> 添加用户 </a>
|
|
||||||
<a id="del_btn" class="btn btn-sm btn-danger "> 删除所选 </a>
|
|
||||||
<form id="search_form" method="get" action="" class="pull-right mail-search">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control input-sm" name="keyword" placeholder="用户名或姓名" value="{{ keyword }}">
|
|
||||||
<div class="input-group-btn">
|
|
||||||
<button id='search_btn' type="submit" class="btn btn-sm btn-primary">
|
|
||||||
搜索
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<table class="table table-striped table-bordered table-hover " id="editable" >
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="text-center">
|
|
||||||
<input type="checkbox" id="check_all" onclick="checkAll('check_all', 'checked')">
|
|
||||||
</th>
|
|
||||||
<th class="text-center"><a href="{% url 'users:user-list' %}?sort=name">姓名</a></th>
|
|
||||||
<th class="text-center"><a href="{% url 'users:user-list' %}?sort=username">用户名</a></th>
|
|
||||||
<th class="text-center">角色</th>
|
|
||||||
<th class="text-center">用户组</th>
|
|
||||||
<th class="text-center">资产数量</th>
|
|
||||||
<th class="text-center"><a href="{% url 'users:user-list' %}?sort=date_expired">有效</a></th>
|
|
||||||
<th class="text-center"></th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{% for user in user_list %}
|
|
||||||
<tr class="gradeX">
|
|
||||||
<td class="text-center">
|
|
||||||
<input type="checkbox" name="checked" value="{{ user.id }}">
|
|
||||||
</td>
|
|
||||||
<td class="text-center">
|
|
||||||
<a href="{% url 'users:user-detail' pk=user.id %}">
|
|
||||||
{{ user.name }}
|
|
||||||
</a>
|
|
||||||
</td>
|
|
||||||
<td class="text-center">{{ user.username }}</td>
|
|
||||||
<td class="text-center">{{ user.role.name }}</td>
|
|
||||||
<td class="text-center" title="{% for user_group in user.group.all %} {{ user_group.name }} {% endfor %}"> {{ user.groups.all|join_queryset_attr:"name" }} </td>
|
|
||||||
<th class="text-center">{{ user.name }}</th>
|
|
||||||
<td class="text-center">
|
|
||||||
{% if user.is_expired %}
|
|
||||||
<i class="fa fa-times text-danger"></i>
|
|
||||||
{% else %}
|
|
||||||
<i class="fa fa-check text-navy"></i>
|
|
||||||
{% endif %}
|
|
||||||
</td>
|
|
||||||
<td class="text-center">
|
|
||||||
<a href="{% url 'users:user-edit' pk=user.id %}" class="btn btn-xs btn-info">编辑</a>
|
|
||||||
<a href="{% url 'users:user-delete' pk=user.id %}" class="btn btn-xs btn-danger del {% if user.username == 'admin' %} disabled {% endif %}">删除</a>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{% endfor %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-6">
|
|
||||||
</div>
|
|
||||||
{% include '_pagination.html' %}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
|
@ -1,20 +1,20 @@
|
||||||
{% extends '_list_base.html' %}
|
{% extends '_list_base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
{% load common_tags %}
|
{% load common_tags %}
|
||||||
{% block content_left_head %}
|
{% block content_left_head %}
|
||||||
<a href="{% url 'users:user-add' %}" class="btn btn-sm btn-primary "> 添加用户 </a>
|
<a href="{% url 'users:user-add' %}" class="btn btn-sm btn-primary "> {% trans "Create user" %} </a>
|
||||||
{# <a id="del_btn" class="btn btn-sm btn-danger "> 删除所选 </a>#}
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block table_head %}
|
{% block table_head %}
|
||||||
<th class="text-center">
|
<th class="text-center">
|
||||||
<input type="checkbox" id="check_all" onclick="checkAll('check_all', 'checked')">
|
<input type="checkbox" id="check_all" onclick="checkAll('check_all', 'checked')">
|
||||||
</th>
|
</th>
|
||||||
<th class="text-center"><a href="{% url 'users:user-list' %}?sort=name">姓名</a></th>
|
<th class="text-center"><a href="{% url 'users:user-list' %}?sort=name">{% trans 'Name' %}</a></th>
|
||||||
<th class="text-center"><a href="{% url 'users:user-list' %}?sort=username">用户名</a></th>
|
<th class="text-center"><a href="{% url 'users:user-list' %}?sort=username">{% trans 'Username' %}</a></th>
|
||||||
<th class="text-center">角色</th>
|
<th class="text-center">{% trans 'Role' %}</th>
|
||||||
<th class="text-center">用户组</th>
|
<th class="text-center">{% trans 'Usergroup' %}</th>
|
||||||
<th class="text-center">资产数量</th>
|
<th class="text-center">{% trans 'Asset num' %}</th>
|
||||||
<th class="text-center"><a href="{% url 'users:user-list' %}?sort=date_expired">有效</a></th>
|
<th class="text-center"><a href="{% url 'users:user-list' %}?sort=date_expired">{% trans 'Active' %}</a></th>
|
||||||
<th class="text-center"></th>
|
<th class="text-center"></th>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
@ -41,8 +41,8 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
<td class="text-center">
|
<td class="text-center">
|
||||||
<a href="{% url 'users:user-edit' pk=user.id %}" class="btn btn-xs btn-info">编辑</a>
|
<a href="{% url 'users:user-edit' pk=user.id %}" class="btn btn-xs btn-info">{% trans 'Edit' %}</a>
|
||||||
<a href="{% url 'users:user-delete' pk=user.id %}" class="btn btn-xs btn-danger del {% if user.id == request.user.id or user.username == 'admin' %} disabled {% endif %}">删除</a>
|
<a href="{% url 'users:user-delete' pk=user.id %}" class="btn btn-xs btn-danger del {% if user.id == request.user.id or user.username == 'admin' %} disabled {% endif %}">{% trans 'Delete' %}</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
@ -52,15 +52,15 @@
|
||||||
<form id="" method="get" action="" class=" mail-search">
|
<form id="" method="get" action="" class=" mail-search">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<select class="form-control m-b" style="width: auto">
|
<select class="form-control m-b" style="width: auto">
|
||||||
<option>批量删除</option>
|
<option>{% trans 'Delete selected' %}</option>
|
||||||
<option>批量更新</option>
|
<option>{% trans 'Update selected' %}</option>
|
||||||
<option>批量禁用</option>
|
<option>{% trans 'Deactive selected' %}</option>
|
||||||
<option>批量导出</option>
|
<option>{% trans 'Export selected' %}</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<div class="input-group-btn pull-left" style="padding-left: 5px;">
|
<div class="input-group-btn pull-left" style="padding-left: 5px;">
|
||||||
<button id='search_btn' type="submit" style="height: 32px;" class="btn btn-sm btn-primary">
|
<button id='search_btn' type="submit" style="height: 32px;" class="btn btn-sm btn-primary">
|
||||||
确认
|
{% trans 'Commit' %}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from django.conf.urls import url
|
from django.conf.urls import url, include
|
||||||
from django.contrib.auth import views as auth_views
|
from django.contrib.auth import views as auth_views
|
||||||
|
from django.urls import reverse_lazy
|
||||||
|
|
||||||
import views
|
import views
|
||||||
import api
|
import api
|
||||||
|
@ -7,23 +8,23 @@ import api
|
||||||
app_name = 'users'
|
app_name = 'users'
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
url(r'^login$', auth_views.login, {'template_name': 'users/login.html'}, name='login'),
|
url(r'^login$', views.UserLoginView.as_view(), name='login'),
|
||||||
url(r'^logout$', auth_views.logout, {'template_name': 'users/login.html'}, name='logout'),
|
url(r'^logout$', views.UserLogoutView.as_view(), name='logout'),
|
||||||
url(r'^password/forget$', views.UserForgetPasswordView.as_view(), name='forget-password'),
|
url(r'^password/forget$', views.UserForgetPasswordView.as_view(), name='forget-password'),
|
||||||
url(r'^password/forget/sendmail-success$',
|
url(r'^password/forget/sendmail-success$',
|
||||||
views.UserForgetPasswordSendmailSuccessView.as_view(), name='forget-password-sendmail-success'),
|
views.UserForgetPasswordSendmailSuccessView.as_view(), name='forget-password-sendmail-success'),
|
||||||
url(r'^password/reset$', views.UserResetPasswordView.as_view(), name='reset-password'),
|
url(r'^password/reset$', views.UserResetPasswordView.as_view(), name='reset-password'),
|
||||||
url(r'^password/reset/success$', views.UserResetPasswordSuccessView.as_view(), name='reset-password-success'),
|
url(r'^password/reset/success$', views.UserResetPasswordSuccessView.as_view(), name='reset-password-success'),
|
||||||
url(r'^users$', views.UserListView.as_view(), name='user-list'),
|
url(r'^user$', views.UserListView.as_view(), name='user-list'),
|
||||||
url(r'^users/(?P<pk>[0-9]+)$', views.UserDetailView.as_view(), name='user-detail'),
|
url(r'^user/(?P<pk>[0-9]+)$', views.UserDetailView.as_view(), name='user-detail'),
|
||||||
url(r'^users/add$', views.UserAddView.as_view(), name='user-add'),
|
url(r'^user/add$', views.UserAddView.as_view(), name='user-add'),
|
||||||
url(r'^users/(?P<pk>[0-9]+)/edit$', views.UserUpdateView.as_view(), name='user-edit'),
|
url(r'^user/(?P<pk>[0-9]+)/edit$', views.UserUpdateView.as_view(), name='user-edit'),
|
||||||
url(r'^users/(?P<pk>[0-9]+)/delete$', views.UserDeleteView.as_view(), name='user-delete'),
|
url(r'^user/(?P<pk>[0-9]+)/delete$', views.UserDeleteView.as_view(), name='user-delete'),
|
||||||
url(r'^usergroups$', views.UserGroupListView.as_view(), name='usergroup-list'),
|
url(r'^usergroup$', views.UserGroupListView.as_view(), name='usergroup-list'),
|
||||||
url(r'^usergroups/(?P<pk>[0-9]+)$', views.UserGroupDetailView.as_view(), name='usergroup-detail'),
|
url(r'^usergroup/(?P<pk>[0-9]+)$', views.UserGroupDetailView.as_view(), name='usergroup-detail'),
|
||||||
url(r'^usergroups/add/$', views.UserGroupAddView.as_view(), name='usergroup-add'),
|
url(r'^usergroup/add/$', views.UserGroupAddView.as_view(), name='usergroup-add'),
|
||||||
url(r'^usergroups/(?P<pk>[0-9]+)/edit$', views.UserGroupUpdateView.as_view(), name='usergroup-edit'),
|
url(r'^usergroup/(?P<pk>[0-9]+)/edit$', views.UserGroupUpdateView.as_view(), name='usergroup-edit'),
|
||||||
url(r'^usergroups/(?P<pk>[0-9]+)/delete$', views.UserGroupDeleteView.as_view(), name='usergroup-delete'),
|
url(r'^usergroup/(?P<pk>[0-9]+)/delete$', views.UserGroupDeleteView.as_view(), name='usergroup-delete'),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import logging
|
||||||
from paramiko.rsakey import RSAKey
|
from paramiko.rsakey import RSAKey
|
||||||
from django.contrib.auth.mixins import UserPassesTestMixin
|
from django.contrib.auth.mixins import UserPassesTestMixin
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from common.tasks import send_mail_async
|
from common.tasks import send_mail_async
|
||||||
from common.utils import reverse
|
from common.utils import reverse
|
||||||
|
@ -43,7 +44,7 @@ def ssh_key_gen(length=2048, password=None, username='root', hostname=None):
|
||||||
f = StringIO.StringIO()
|
f = StringIO.StringIO()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
logger.debug('Begin to generate ssh private key ...')
|
logger.debug(_('Begin to generate ssh private key ...'))
|
||||||
private_key_obj = RSAKey.generate(length)
|
private_key_obj = RSAKey.generate(length)
|
||||||
private_key_obj.write_private_key(f, password=password)
|
private_key_obj.write_private_key(f, password=password)
|
||||||
private_key = f.getvalue()
|
private_key = f.getvalue()
|
||||||
|
@ -55,33 +56,33 @@ def ssh_key_gen(length=2048, password=None, username='root', hostname=None):
|
||||||
'hostname': hostname,
|
'hostname': hostname,
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.debug('Finish to generate ssh private key ...')
|
logger.debug(_('Finish to generate ssh private key ...'))
|
||||||
return private_key, public_key
|
return private_key, public_key
|
||||||
|
|
||||||
except IOError:
|
except IOError:
|
||||||
raise IOError('These is error when generate ssh key.')
|
raise IOError(_('These is error when generate ssh key.'))
|
||||||
|
|
||||||
|
|
||||||
def user_add_success_next(user):
|
def user_add_success_next(user):
|
||||||
subject = '您的用户创建成功'
|
subject = _('Create account successfully')
|
||||||
recipient_list = [user.email]
|
recipient_list = [user.email]
|
||||||
message = """
|
message = _("""
|
||||||
您好 %(name)s:
|
Hello %(name)s:
|
||||||
</br>
|
</br>
|
||||||
恭喜您,您的账号已经创建成功.
|
Your account has been created successfully
|
||||||
</br>
|
</br>
|
||||||
<a href="%(rest_password_url)s?token=%(rest_password_token)s">请点击这里设置密码</a>
|
<a href="%(rest_password_url)s?token=%(rest_password_token)s">click here to set your password</a>
|
||||||
</br>
|
</br>
|
||||||
这个链接有效期1小时, 超过时间您可以 <a href="%(forget_password_url)s?email=%(email)s">重新申请</a>
|
This link is valid for 1 hour. After it expires, <a href="%(forget_password_url)s?email=%(email)s">request new one</a>
|
||||||
|
|
||||||
</br>
|
</br>
|
||||||
---
|
---
|
||||||
|
|
||||||
</br>
|
</br>
|
||||||
<a href="%(login_url)s">直接登录</a>
|
<a href="%(login_url)s">Login direct</a>
|
||||||
|
|
||||||
</br>
|
</br>
|
||||||
""" % {
|
""") % {
|
||||||
'name': user.name,
|
'name': user.name,
|
||||||
'rest_password_url': reverse('users:reset-password', external=True),
|
'rest_password_url': reverse('users:reset-password', external=True),
|
||||||
'rest_password_token': user.generate_reset_token(),
|
'rest_password_token': user.generate_reset_token(),
|
||||||
|
@ -94,25 +95,25 @@ def user_add_success_next(user):
|
||||||
|
|
||||||
|
|
||||||
def send_reset_password_mail(user):
|
def send_reset_password_mail(user):
|
||||||
subject = '重设密码'
|
subject = _('Reset password')
|
||||||
recipient_list = [user.email]
|
recipient_list = [user.email]
|
||||||
message = """
|
message = _("""
|
||||||
您好 %(name)s:
|
Hello %(name)s:
|
||||||
</br>
|
</br>
|
||||||
您好,请点击下面链接重置密码, 如果不是您申请的, 请关注账号安全
|
Please click the link below to reset your password, if not your request, concern your account security
|
||||||
</br>
|
</br>
|
||||||
<a href="%(rest_password_url)s?token=%(rest_password_token)s">请点击这里设置密码</a>
|
<a href="%(rest_password_url)s?token=%(rest_password_token)s">Click here reset password</a>
|
||||||
</br>
|
</br>
|
||||||
这个链接有效期1小时, 超过时间您可以 <a href="%(forget_password_url)s?email=%(email)s">重新申请</a>
|
This link is valid for 1 hour. After it expires, <a href="%(forget_password_url)s?email=%(email)s">request new one<</a>
|
||||||
|
|
||||||
</br>
|
</br>
|
||||||
---
|
---
|
||||||
|
|
||||||
</br>
|
</br>
|
||||||
<a href="%(login_url)s">直接登录</a>
|
<a href="%(login_url)s">Login direct</a>
|
||||||
|
|
||||||
</br>
|
</br>
|
||||||
""" % {
|
""") % {
|
||||||
'name': user.name,
|
'name': user.name,
|
||||||
'rest_password_url': reverse('users:reset-password', external=True),
|
'rest_password_url': reverse('users:reset-password', external=True),
|
||||||
'rest_password_token': user.generate_reset_token(),
|
'rest_password_token': user.generate_reset_token(),
|
||||||
|
|
|
@ -4,9 +4,9 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from django.shortcuts import get_object_or_404, reverse, render, Http404
|
from django.shortcuts import get_object_or_404, reverse, render, Http404, redirect
|
||||||
from django.http import HttpResponseRedirect
|
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.views.generic.base import View, TemplateView
|
from django.views.generic.base import View, TemplateView
|
||||||
from django.views.generic.list import ListView
|
from django.views.generic.list import ListView
|
||||||
|
@ -15,6 +15,7 @@ from django.views.generic.detail import DetailView
|
||||||
from django.contrib.messages.views import SuccessMessageMixin
|
from django.contrib.messages.views import SuccessMessageMixin
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.http import HttpResponseRedirect
|
from django.http import HttpResponseRedirect
|
||||||
|
from django.contrib.auth import views as auth_view, authenticate, login, logout
|
||||||
|
|
||||||
from common.utils import get_object_or_none
|
from common.utils import get_object_or_none
|
||||||
|
|
||||||
|
@ -26,6 +27,55 @@ from .utils import AdminUserRequiredMixin, ssh_key_gen, user_add_success_next, s
|
||||||
logger = logging.getLogger('jumpserver.users.views')
|
logger = logging.getLogger('jumpserver.users.views')
|
||||||
|
|
||||||
|
|
||||||
|
class UserLoginView(FormView):
|
||||||
|
template_name = 'users/login.html'
|
||||||
|
form_class = UserLoginForm
|
||||||
|
redirect_field_name = 'next'
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
if self.request.user.is_staff:
|
||||||
|
return redirect(request.POST.get(self.redirect_field_name, reverse('index')))
|
||||||
|
# Todo: Django have bug, lose context issue: https://github.com/django/django/pull/7202
|
||||||
|
# so we jump it and use origin method render_to_response
|
||||||
|
# return super(UserLoginView, self).get(request, *args, **kwargs)
|
||||||
|
return self.render_to_response(self.get_context_data(**kwargs))
|
||||||
|
|
||||||
|
def post(self, request, *args, **kwargs):
|
||||||
|
form = self.get_form()
|
||||||
|
if not form.is_valid():
|
||||||
|
return self.form_invalid(form)
|
||||||
|
|
||||||
|
username = form['username'].value()
|
||||||
|
password = form['password'].value()
|
||||||
|
|
||||||
|
user = authenticate(username=username, password=password)
|
||||||
|
if user is None:
|
||||||
|
kwargs.update({'errors': _('Username or password invalid')})
|
||||||
|
return self.get(request, *args, **kwargs)
|
||||||
|
|
||||||
|
login(request, user)
|
||||||
|
return redirect(request.GET.get(self.redirect_field_name, reverse('index')))
|
||||||
|
|
||||||
|
|
||||||
|
class UserLogoutView(TemplateView):
|
||||||
|
template_name = 'common/flash_message_standalone.html'
|
||||||
|
|
||||||
|
def get(self, request, *args, **kwargs):
|
||||||
|
logout(request)
|
||||||
|
|
||||||
|
return super(UserLogoutView, self).get(request)
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = {
|
||||||
|
'title': _('Logout success'),
|
||||||
|
'messages': _('Logout success, return login page'),
|
||||||
|
'redirect_url': reverse('users:login'),
|
||||||
|
'auto_redirect': True,
|
||||||
|
}
|
||||||
|
kwargs.update(context)
|
||||||
|
return super(UserLogoutView, self).get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class UserListView(AdminUserRequiredMixin, ListView):
|
class UserListView(AdminUserRequiredMixin, ListView):
|
||||||
model = User
|
model = User
|
||||||
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
|
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
|
||||||
|
@ -47,7 +97,7 @@ class UserListView(AdminUserRequiredMixin, ListView):
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(UserListView, self).get_context_data(**kwargs)
|
context = super(UserListView, self).get_context_data(**kwargs)
|
||||||
context.update({'app': '用户管理', 'action': '用户列表', 'keyword': self.keyword})
|
context.update({'app': _('Users'), 'action': _('User list'), 'keyword': self.keyword})
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
@ -56,11 +106,11 @@ class UserAddView(AdminUserRequiredMixin, SuccessMessageMixin, CreateView):
|
||||||
form_class = UserAddForm
|
form_class = UserAddForm
|
||||||
template_name = 'users/user_add.html'
|
template_name = 'users/user_add.html'
|
||||||
success_url = reverse_lazy('users:user-list')
|
success_url = reverse_lazy('users:user-list')
|
||||||
success_message = '添加用户 <a href="%s">%s</a> 成功 .'
|
success_message = _('Create user<a href="%s">%s</a> success.')
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(UserAddView, self).get_context_data(**kwargs)
|
context = super(UserAddView, self).get_context_data(**kwargs)
|
||||||
context.update({'app': '用户管理', 'action': '用户添加'})
|
context.update({'app': _('Users'), 'action': _('Create user')})
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
|
@ -102,7 +152,7 @@ class UserUpdateView(AdminUserRequiredMixin, UpdateView):
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(UserUpdateView, self).get_context_data(**kwargs)
|
context = super(UserUpdateView, self).get_context_data(**kwargs)
|
||||||
context.update({'app': '用户管理', 'action': '用户编辑'})
|
context.update({'app': _('Users'), 'action': _('Edit user')})
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
@ -120,7 +170,7 @@ class UserDetailView(AdminUserRequiredMixin, DetailView):
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(UserDetailView, self).get_context_data(**kwargs)
|
context = super(UserDetailView, self).get_context_data(**kwargs)
|
||||||
groups = [group for group in UserGroup.objects.iterator() if group not in self.object.groups.iterator()]
|
groups = [group for group in UserGroup.objects.iterator() if group not in self.object.groups.iterator()]
|
||||||
context.update({'app': '用户管理', 'action': '用户详情', 'groups': groups})
|
context.update({'app': _('Users'), 'action': _('User detail'), 'groups': groups})
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
@ -144,7 +194,7 @@ class UserGroupListView(AdminUserRequiredMixin, ListView):
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(UserGroupListView, self).get_context_data(**kwargs)
|
context = super(UserGroupListView, self).get_context_data(**kwargs)
|
||||||
context.update({'app': '用户管理', 'action': '用户组列表', 'keyword': self.keyword})
|
context.update({'app': _('Users'), 'action': _('Usergroup list'), 'keyword': self.keyword})
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
|
||||||
|
@ -157,7 +207,7 @@ class UserGroupAddView(AdminUserRequiredMixin, CreateView):
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = super(UserGroupAddView, self).get_context_data(**kwargs)
|
context = super(UserGroupAddView, self).get_context_data(**kwargs)
|
||||||
users = User.objects.all()
|
users = User.objects.all()
|
||||||
context.update({'app': '用户管理', 'action': '用户组添加', 'users': users})
|
context.update({'app': _('Users'), 'action': _('Create usergroup'), 'users': users})
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def form_valid(self, form):
|
def form_valid(self, form):
|
||||||
|
@ -189,7 +239,7 @@ class UserForgetPasswordView(TemplateView):
|
||||||
email = request.POST.get('email')
|
email = request.POST.get('email')
|
||||||
user = get_object_or_none(User, email=email)
|
user = get_object_or_none(User, email=email)
|
||||||
if not user:
|
if not user:
|
||||||
return self.get(request, errors='邮件地址错误,请重新输入')
|
return self.get(request, errors=_('Email address invalid, input again'))
|
||||||
else:
|
else:
|
||||||
send_reset_password_mail(user)
|
send_reset_password_mail(user)
|
||||||
return HttpResponseRedirect(reverse('users:forget-password-sendmail-success'))
|
return HttpResponseRedirect(reverse('users:forget-password-sendmail-success'))
|
||||||
|
@ -200,8 +250,8 @@ class UserForgetPasswordSendmailSuccessView(TemplateView):
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = {
|
context = {
|
||||||
'title': '发送重置邮件',
|
'title': _('Send reset password message'),
|
||||||
'messages': '发送重置邮件成功, 请登录邮箱查看, 按照提示操作 (如果没收到,请等待3-5分钟)',
|
'messages': _('Send reset password mail success, login your mail box and follow it '),
|
||||||
'redirect_url': reverse('users:login'),
|
'redirect_url': reverse('users:login'),
|
||||||
}
|
}
|
||||||
kwargs.update(context)
|
kwargs.update(context)
|
||||||
|
@ -213,9 +263,10 @@ class UserResetPasswordSuccessView(TemplateView):
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = {
|
context = {
|
||||||
'title': '重设密码成功',
|
'title': _('Reset password success'),
|
||||||
'messages': '密码重置成功, 请返回登录页面登录系统',
|
'messages': _('Reset password success, return to login page'),
|
||||||
'redirect_url': reverse('users:login'),
|
'redirect_url': reverse('users:login'),
|
||||||
|
'auto_redirect': True,
|
||||||
}
|
}
|
||||||
kwargs.update(context)
|
kwargs.update(context)
|
||||||
return super(UserResetPasswordSuccessView, self).get_context_data(**kwargs)
|
return super(UserResetPasswordSuccessView, self).get_context_data(**kwargs)
|
||||||
|
@ -229,7 +280,7 @@ class UserResetPasswordView(TemplateView):
|
||||||
user = User.validate_reset_token(token)
|
user = User.validate_reset_token(token)
|
||||||
|
|
||||||
if not user:
|
if not user:
|
||||||
kwargs.update({'errors': 'Token不正确或已过期'})
|
kwargs.update({'errors': _('Token invalid or expired')})
|
||||||
return super(UserResetPasswordView, self).get(request, *args, **kwargs)
|
return super(UserResetPasswordView, self).get(request, *args, **kwargs)
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
|
@ -238,11 +289,11 @@ class UserResetPasswordView(TemplateView):
|
||||||
token = request.GET.get('token')
|
token = request.GET.get('token')
|
||||||
|
|
||||||
if password != password_confirm:
|
if password != password_confirm:
|
||||||
return self.get(request, errors='两次密码不匹配')
|
return self.get(request, errors=_('Password not same'))
|
||||||
|
|
||||||
user = User.validate_reset_token(token)
|
user = User.validate_reset_token(token)
|
||||||
if not user:
|
if not user:
|
||||||
return self.get(request, errors='Token不正确或已过期')
|
return self.get(request, errors=_('Token invalid or expired'))
|
||||||
|
|
||||||
user.reset_password(password)
|
user.reset_password(password)
|
||||||
return HttpResponseRedirect(reverse('users:reset-password-success'))
|
return HttpResponseRedirect(reverse('users:reset-password-success'))
|
||||||
|
|
|
@ -23,6 +23,7 @@ class Config:
|
||||||
# It's used to identify your site, When we send a create mail to user, we only know login url is /login/
|
# It's used to identify your site, When we send a create mail to user, we only know login url is /login/
|
||||||
# But we should know the absolute url like: http://jms.jumpserver.org/login/, so SITE_URL is
|
# But we should know the absolute url like: http://jms.jumpserver.org/login/, so SITE_URL is
|
||||||
# HTTP_PROTOCOL://HOST[:PORT]
|
# HTTP_PROTOCOL://HOST[:PORT]
|
||||||
|
# Todo: May be use :method: get_current_site more grace, bug restful api unknown ok or not
|
||||||
SITE_URL = 'http://localhost'
|
SITE_URL = 'http://localhost'
|
||||||
|
|
||||||
# Django security setting, if your disable debug model, you should setting that
|
# Django security setting, if your disable debug model, you should setting that
|
||||||
|
@ -52,7 +53,7 @@ class Config:
|
||||||
# When Django start it will bind this host and port
|
# When Django start it will bind this host and port
|
||||||
# ./manage.py runserver 127.0.0.1:8080
|
# ./manage.py runserver 127.0.0.1:8080
|
||||||
# Todo: Gunicorn or uwsgi run may be use it
|
# Todo: Gunicorn or uwsgi run may be use it
|
||||||
HTTP_LISTEN_HOST = '127.0.0.1'
|
HTTP_LISTEN_HOST = '0.0.0.0'
|
||||||
HTTP_LISTEN_PORT = 8080
|
HTTP_LISTEN_PORT = 8080
|
||||||
|
|
||||||
# Use Redis as broker for celery and web socket
|
# Use Redis as broker for celery and web socket
|
||||||
|
|
|
@ -21,14 +21,15 @@ https://example.org/api/
|
||||||
|
|
||||||
### 版本
|
### 版本
|
||||||
|
|
||||||
将API的版本号放入URL
|
将API的版本号放入URL中, 由于一个项目多个app所以Jumpserver使用以下风格,
|
||||||
|
将版本号放到app后面
|
||||||
|
|
||||||
```
|
```
|
||||||
https://example.com/api/v1/
|
https://example.com/api/:app:/:version:/:resource:
|
||||||
|
https://example.com/api/assets/v1.0/assets [GET, POST]
|
||||||
|
https://example.com/api/assets/v1.0/assets/1 [GET, PUT, DELETE]
|
||||||
```
|
```
|
||||||
|
|
||||||
另一种做法是,将版本号放在HTTP头信息中,但不如放入URL方便和直观。Github采用这种做法。
|
|
||||||
|
|
||||||
|
|
||||||
### 路径
|
### 路径
|
||||||
|
|
||||||
|
@ -37,11 +38,11 @@ https://example.com/api/v1/
|
||||||
举例来说 cmdb中的assets列表, idc列表
|
举例来说 cmdb中的assets列表, idc列表
|
||||||
|
|
||||||
```
|
```
|
||||||
https://example.com/api/v1/assets
|
https://example.com/api/:app:/:version:/:resource:
|
||||||
https://example.com/api/v1/assetgroups
|
|
||||||
https://example.com/api/v1/assetgroups/:id/assets
|
https://example.com/api/assets/v1.0/assets [GET, POST]
|
||||||
https://example.com/api/v1/assets/:id
|
https://example.com/api/assets/v1.0/assets/1 [GET, PUT, DELETE]
|
||||||
https://example.com/api/v1/idcs
|
https://example.com/api/assets/v1.0/idcs [GET, POST]
|
||||||
```
|
```
|
||||||
|
|
||||||
一般性的增删查改(CRUD)API,完全使用HTTP method加上url提供的语义,url中的可变部分(比如上面提到的<role_id>)
|
一般性的增删查改(CRUD)API,完全使用HTTP method加上url提供的语义,url中的可变部分(比如上面提到的<role_id>)
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
├── README.md
|
├── README.md
|
||||||
├── install // 安装说明
|
├── install // 安装说明
|
||||||
├── logs // 日志目录
|
├── logs // 日志目录
|
||||||
├── apps // 管理后台目录,也是各app所在目录
|
├── apps // 管理后台目录,也是各app所在目录
|
||||||
│ └── assets // app目录
|
│ └── assets // app目录
|
||||||
│ │ ├── admin.py
|
│ │ ├── admin.py
|
||||||
│ │ ├── apps.py // 新版本django app设置文件
|
│ │ ├── apps.py // 新版本django app设置文件
|
||||||
|
@ -35,7 +35,7 @@
|
||||||
│ │ ├── templatetags // 通用template tag
|
│ │ ├── templatetags // 通用template tag
|
||||||
│ │ ├── utils.py // 通用的函数方法
|
│ │ ├── utils.py // 通用的函数方法
|
||||||
│ │ └── views.py
|
│ │ └── views.py
|
||||||
│ ├── fixtures // 初始化数据目录
|
│ ├── fixtures // 初始化数据目录
|
||||||
│ │ ├── init.json // 初始化项目数据库
|
│ │ ├── init.json // 初始化项目数据库
|
||||||
│ │ └── fake.json // 生成大量测试数据
|
│ │ └── fake.json // 生成大量测试数据
|
||||||
│ ├── jumpserver // 项目设置目录
|
│ ├── jumpserver // 项目设置目录
|
||||||
|
@ -45,5 +45,6 @@
|
||||||
│ │ └── wsgi.py
|
│ │ └── wsgi.py
|
||||||
│ ├── manage.py
|
│ ├── manage.py
|
||||||
│ ├── static // 项目静态资源目录
|
│ ├── static // 项目静态资源目录
|
||||||
|
│ ├── static // 项目多语言目录
|
||||||
│ └── templates // 项目模板目录
|
│ └── templates // 项目模板目录
|
||||||
```
|
```
|
||||||
|
|
|
@ -16,3 +16,4 @@ ForgeryPy==0.1
|
||||||
paramiko==2.0.2
|
paramiko==2.0.2
|
||||||
celery==3.1.23
|
celery==3.1.23
|
||||||
ansible==2.1.1.0
|
ansible==2.1.1.0
|
||||||
|
django-simple-captcha==0.5.2
|
||||||
|
|
Loading…
Reference in New Issue