mirror of https://github.com/jumpserver/jumpserver
Add admin user list view
parent
dfc628a397
commit
6f4a832389
|
@ -11,4 +11,4 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
from users.utils import AdminUserRequiredMixin
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Generated by Django 1.10 on 2016-09-05 12:50
|
# Generated by Django 1.10 on 2016-09-07 15:11
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
@ -24,12 +24,12 @@ class Migration(migrations.Migration):
|
||||||
('private_key', models.CharField(blank=True, max_length=4096, null=True, verbose_name='SSH private key')),
|
('private_key', models.CharField(blank=True, max_length=4096, null=True, verbose_name='SSH private key')),
|
||||||
('is_default', models.BooleanField(default=True, verbose_name='As default')),
|
('is_default', models.BooleanField(default=True, verbose_name='As default')),
|
||||||
('auto_update', models.BooleanField(default=True, verbose_name='Auto update pass/key')),
|
('auto_update', models.BooleanField(default=True, verbose_name='Auto update pass/key')),
|
||||||
('date_added', models.DateTimeField(auto_now=True, null=True)),
|
('date_created', models.DateTimeField(auto_now=True, null=True)),
|
||||||
('create_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')),
|
('create_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')),
|
||||||
('comment', models.TextField(blank=True, verbose_name='Comment')),
|
('comment', models.TextField(blank=True, verbose_name='Comment')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'db_table': 'adminuser',
|
'db_table': 'admin_user',
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
|
@ -55,9 +55,9 @@ class Migration(migrations.Migration):
|
||||||
('sn', models.CharField(blank=True, max_length=128, null=True, unique=True, verbose_name='Serial number')),
|
('sn', models.CharField(blank=True, max_length=128, null=True, unique=True, verbose_name='Serial number')),
|
||||||
('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')),
|
('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')),
|
||||||
('is_active', models.BooleanField(default=True, verbose_name='Is active')),
|
('is_active', models.BooleanField(default=True, verbose_name='Is active')),
|
||||||
('date_added', models.DateTimeField(auto_now=True, null=True, verbose_name='Date added')),
|
('date_created', models.DateTimeField(auto_now=True, null=True, verbose_name='Date added')),
|
||||||
('comment', models.CharField(blank=True, max_length=128, null=True, verbose_name='Comment')),
|
('comment', models.CharField(blank=True, max_length=128, null=True, verbose_name='Comment')),
|
||||||
('admin_user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.AdminUser', verbose_name='Admin user')),
|
('admin_user', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.AdminUser', verbose_name='Admin user')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'db_table': 'asset',
|
'db_table': 'asset',
|
||||||
|
@ -70,23 +70,24 @@ class Migration(migrations.Migration):
|
||||||
('key', models.CharField(blank=True, max_length=64, null=True, verbose_name='KEY')),
|
('key', models.CharField(blank=True, max_length=64, null=True, verbose_name='KEY')),
|
||||||
('value', models.CharField(blank=True, max_length=64, null=True, verbose_name='VALUE')),
|
('value', models.CharField(blank=True, max_length=64, null=True, verbose_name='VALUE')),
|
||||||
('created_by', models.CharField(blank=True, max_length=32, verbose_name='Created by')),
|
('created_by', models.CharField(blank=True, max_length=32, verbose_name='Created by')),
|
||||||
('date_added', models.DateTimeField(auto_now=True, null=True)),
|
('date_created', models.DateTimeField(auto_now=True, null=True)),
|
||||||
('comment', models.TextField(blank=True, verbose_name='Comment')),
|
('comment', models.TextField(blank=True, verbose_name='Comment')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'db_table': 'assetextend',
|
'db_table': 'asset_extend',
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='AssetGroup',
|
name='AssetGroup',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('name', models.CharField(blank=True, max_length=64, null=True, unique=True, verbose_name='Name')),
|
('name', models.CharField(max_length=64, unique=True, verbose_name='Name')),
|
||||||
('created_by', models.CharField(blank=True, max_length=32, null=True, verbose_name='Created by')),
|
('created_by', models.CharField(blank=True, max_length=32, verbose_name='Created by')),
|
||||||
|
('date_created', models.DateTimeField(auto_now=True, null=True, verbose_name='Date added')),
|
||||||
('comment', models.TextField(blank=True, verbose_name='Comment')),
|
('comment', models.TextField(blank=True, verbose_name='Comment')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'db_table': 'assetgroup',
|
'db_table': 'asset_group',
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
|
@ -99,7 +100,7 @@ class Migration(migrations.Migration):
|
||||||
('phone', models.CharField(blank=True, max_length=32, verbose_name='Phone')),
|
('phone', models.CharField(blank=True, max_length=32, verbose_name='Phone')),
|
||||||
('address', models.CharField(blank=True, max_length=128, verbose_name='Address')),
|
('address', models.CharField(blank=True, max_length=128, verbose_name='Address')),
|
||||||
('network', models.TextField(blank=True, verbose_name='Network')),
|
('network', models.TextField(blank=True, verbose_name='Network')),
|
||||||
('date_added', models.DateField(auto_now=True, null=True, verbose_name='Date added')),
|
('date_created', models.DateTimeField(auto_now=True, null=True, verbose_name='Date added')),
|
||||||
('operator', models.CharField(blank=True, max_length=32, verbose_name='Operator')),
|
('operator', models.CharField(blank=True, max_length=32, verbose_name='Operator')),
|
||||||
('created_by', models.CharField(blank=True, max_length=32, verbose_name='Created by')),
|
('created_by', models.CharField(blank=True, max_length=32, verbose_name='Created by')),
|
||||||
('comment', models.TextField(blank=True, verbose_name='Comment')),
|
('comment', models.TextField(blank=True, verbose_name='Comment')),
|
||||||
|
@ -115,7 +116,7 @@ class Migration(migrations.Migration):
|
||||||
('key', models.CharField(blank=True, max_length=64, null=True, verbose_name='KEY')),
|
('key', models.CharField(blank=True, max_length=64, null=True, verbose_name='KEY')),
|
||||||
('value', models.CharField(blank=True, max_length=64, null=True, verbose_name='VALUE')),
|
('value', models.CharField(blank=True, max_length=64, null=True, verbose_name='VALUE')),
|
||||||
('created_by', models.CharField(blank=True, max_length=32, verbose_name='Created by')),
|
('created_by', models.CharField(blank=True, max_length=32, verbose_name='Created by')),
|
||||||
('date_added', models.DateTimeField(auto_now=True, null=True)),
|
('date_created', models.DateTimeField(auto_now=True, null=True)),
|
||||||
('comment', models.CharField(blank=True, max_length=128, verbose_name='Comment')),
|
('comment', models.CharField(blank=True, max_length=128, verbose_name='Comment')),
|
||||||
('asset', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.Asset', verbose_name='Asset')),
|
('asset', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.Asset', verbose_name='Asset')),
|
||||||
],
|
],
|
||||||
|
@ -124,7 +125,7 @@ class Migration(migrations.Migration):
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='SysUser',
|
name='SystemUser',
|
||||||
fields=[
|
fields=[
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('name', models.CharField(max_length=128, unique=True, verbose_name='Name')),
|
('name', models.CharField(max_length=128, unique=True, verbose_name='Name')),
|
||||||
|
@ -140,14 +141,19 @@ class Migration(migrations.Migration):
|
||||||
('shell', models.CharField(blank=True, max_length=64, verbose_name='Shell')),
|
('shell', models.CharField(blank=True, max_length=64, verbose_name='Shell')),
|
||||||
('home', models.CharField(blank=True, max_length=64, verbose_name='Home')),
|
('home', models.CharField(blank=True, max_length=64, verbose_name='Home')),
|
||||||
('uid', models.IntegerField(blank=True, verbose_name='Uid')),
|
('uid', models.IntegerField(blank=True, verbose_name='Uid')),
|
||||||
('date_added', models.DateTimeField(auto_now=True, null=True)),
|
('date_created', models.DateTimeField(auto_now=True, null=True)),
|
||||||
('create_by', models.CharField(blank=True, max_length=32, verbose_name='Created by')),
|
('create_by', models.CharField(blank=True, max_length=32, verbose_name='Created by')),
|
||||||
('comment', models.CharField(blank=True, max_length=128, verbose_name='Comment')),
|
('comment', models.CharField(blank=True, max_length=128, verbose_name='Comment')),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'db_table': 'sysuser',
|
'db_table': 'system_user',
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='assetgroup',
|
||||||
|
name='system_users',
|
||||||
|
field=models.ManyToManyField(blank=True, related_name='asset_groups', to='assets.SystemUser'),
|
||||||
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='asset',
|
model_name='asset',
|
||||||
name='env',
|
name='env',
|
||||||
|
@ -156,12 +162,12 @@ class Migration(migrations.Migration):
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='asset',
|
model_name='asset',
|
||||||
name='groups',
|
name='groups',
|
||||||
field=models.ManyToManyField(blank=True, null=True, to='assets.AssetGroup', verbose_name='Asset groups'),
|
field=models.ManyToManyField(related_name='assets', to='assets.AssetGroup', verbose_name='Asset groups'),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='asset',
|
model_name='asset',
|
||||||
name='idc',
|
name='idc',
|
||||||
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.IDC', verbose_name='IDC'),
|
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='assets', to='assets.IDC', verbose_name='IDC'),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='asset',
|
model_name='asset',
|
||||||
|
@ -170,8 +176,8 @@ class Migration(migrations.Migration):
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='asset',
|
model_name='asset',
|
||||||
name='sys_user',
|
name='system_user',
|
||||||
field=models.ManyToManyField(blank=True, null=True, to='assets.SysUser', verbose_name='System User'),
|
field=models.ManyToManyField(blank=True, to='assets.SystemUser', verbose_name='System User'),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='asset',
|
model_name='asset',
|
||||||
|
|
|
@ -5,6 +5,8 @@ from django.db import models
|
||||||
import logging
|
import logging
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
from common.utils import encrypt, decrypt
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -68,20 +70,64 @@ class AssetExtend(models.Model):
|
||||||
class AdminUser(models.Model):
|
class AdminUser(models.Model):
|
||||||
name = models.CharField(max_length=128, unique=True, null=True, blank=True, verbose_name=_('Name'))
|
name = models.CharField(max_length=128, unique=True, null=True, blank=True, verbose_name=_('Name'))
|
||||||
username = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('Username'))
|
username = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('Username'))
|
||||||
password = models.CharField(max_length=256, null=True, blank=True, verbose_name=_('Password'))
|
_password = models.CharField(max_length=256, null=True, blank=True, verbose_name=_('Password'))
|
||||||
private_key = models.CharField(max_length=4096, null=True, blank=True, verbose_name=_('SSH private key'))
|
_private_key = models.CharField(max_length=4096, null=True, blank=True, verbose_name=_('SSH private key'))
|
||||||
is_default = models.BooleanField(default=True, verbose_name=_('As default'))
|
_public_key = models.CharField(max_length=4096, null=True, blank=True, verbose_name=_('SSH public key'))
|
||||||
auto_update = models.BooleanField(default=True, verbose_name=_('Auto update pass/key'))
|
as_default = models.BooleanField(default=True, verbose_name=_('As default'))
|
||||||
date_created = models.DateTimeField(auto_now=True, null=True, blank=True)
|
|
||||||
create_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by'))
|
|
||||||
comment = models.TextField(blank=True, verbose_name=_('Comment'))
|
comment = models.TextField(blank=True, verbose_name=_('Comment'))
|
||||||
|
date_created = models.DateTimeField(auto_now=True, null=True, blank=True)
|
||||||
|
created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by'))
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def password(self):
|
||||||
|
return decrypt(self._password)
|
||||||
|
|
||||||
|
@password.setter
|
||||||
|
def password(self, password_raw):
|
||||||
|
self._password = encrypt(password_raw)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def private_key(self):
|
||||||
|
return decrypt(self._private_key)
|
||||||
|
|
||||||
|
@private_key.setter
|
||||||
|
def private_key(self, private_key_raw):
|
||||||
|
self._private_key = encrypt(private_key_raw)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def public_key(self):
|
||||||
|
return decrypt(self._public_key)
|
||||||
|
|
||||||
|
@public_key.setter
|
||||||
|
def public_key(self, public_key_raw):
|
||||||
|
self._public_key = encrypt(public_key_raw)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = 'admin_user'
|
db_table = 'admin_user'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def generate_fake(cls, count=100):
|
||||||
|
from random import seed, choice
|
||||||
|
import forgery_py
|
||||||
|
from django.db import IntegrityError
|
||||||
|
|
||||||
|
seed()
|
||||||
|
for i in range(count):
|
||||||
|
obj = cls(name=forgery_py.name.full_name(),
|
||||||
|
username=forgery_py.internet.user_name(),
|
||||||
|
password=forgery_py.lorem_ipsum.word(),
|
||||||
|
comment=forgery_py.lorem_ipsum.sentence(),
|
||||||
|
created_by='Fake')
|
||||||
|
try:
|
||||||
|
obj.save()
|
||||||
|
logger.debug('Generate fake asset group: %s' % obj.name)
|
||||||
|
except IntegrityError:
|
||||||
|
print('Error continue')
|
||||||
|
continue
|
||||||
|
|
||||||
|
|
||||||
class SystemUser(models.Model):
|
class SystemUser(models.Model):
|
||||||
PROTOCOL_CHOICES = (
|
PROTOCOL_CHOICES = (
|
||||||
|
@ -102,7 +148,7 @@ class SystemUser(models.Model):
|
||||||
home = models.CharField(max_length=64, blank=True, verbose_name=_('Home'))
|
home = models.CharField(max_length=64, blank=True, verbose_name=_('Home'))
|
||||||
uid = models.IntegerField(blank=True, verbose_name=_('Uid'))
|
uid = models.IntegerField(blank=True, verbose_name=_('Uid'))
|
||||||
date_created = models.DateTimeField(auto_now=True, null=True)
|
date_created = models.DateTimeField(auto_now=True, null=True)
|
||||||
create_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by'))
|
created_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by'))
|
||||||
comment = models.CharField(max_length=128, blank=True, verbose_name=_('Comment'))
|
comment = models.CharField(max_length=128, blank=True, verbose_name=_('Comment'))
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
|
@ -223,3 +269,7 @@ class Label(models.Model):
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = 'label'
|
db_table = 'label'
|
||||||
|
|
||||||
|
|
||||||
|
def generate_fake():
|
||||||
|
for cls in (Asset, AssetGroup, IDC):
|
||||||
|
cls.generate_fake()
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
{% extends '_list_base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load common_tags %}
|
||||||
|
{% block content_left_head %}
|
||||||
|
<a href="{% url 'assets:admin-user-create' %}" class="btn btn-sm btn-primary "> {% trans "Create admin user" %} </a>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block table_head %}
|
||||||
|
<th class="text-center">{% trans 'ID' %}</th>
|
||||||
|
<th class="text-center"><a href="{% url 'assets:admin-user-list' %}?sort=name">{% trans 'Name' %}</a></th>
|
||||||
|
<th class="text-center"><a href="{% url 'assets:admin-user-list' %}?sort=username">{% trans 'Username' %}</a></th>
|
||||||
|
<th class="text-center">{% trans 'Asset num' %}</th>
|
||||||
|
<th class="text-center">{% trans 'Lost connection' %}</th>
|
||||||
|
<th class="text-center">{% trans 'Comment' %}</th>
|
||||||
|
<th class="text-center"></th>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block table_body %}
|
||||||
|
{% for admin_user in admin_user_list %}
|
||||||
|
<tr class="gradeX">
|
||||||
|
<td class="text-center">{{ admin_user.id }}</td>
|
||||||
|
<td>
|
||||||
|
<a href="{% url 'users:user-detail' pk=user.id %}">
|
||||||
|
{{ admin_user.name }}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">{{ admin_user.username }}</td>
|
||||||
|
<td class="text-center">{{ admin_user.assets.count }}</td>
|
||||||
|
<td class="text-center">{{ admin_user.assets.count }}</td>
|
||||||
|
<td class="text-center">{{ admin_user.comment|truncatewords:8 }}</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<!-- Todo: Click script button will paste a url to clipboard like: curl http://url/admin_user_create.sh | bash -->
|
||||||
|
<a href="{% url 'assets:admin-user-update' pk=admin_user.id %}" class="btn btn-xs btn-primary">{% trans 'Script' %}</a>
|
||||||
|
<!-- Todo: Click refresh button will run a task to test admin user could connect asset or not immediately -->
|
||||||
|
<a href="{% url 'assets:admin-user-update' pk=admin_user.id %}" class="btn btn-xs btn-warning">{% trans 'Refresh' %}</a>
|
||||||
|
<a href="{% url 'assets:admin-user-update' pk=admin_user.id %}" class="btn btn-xs btn-info">{% trans 'Update' %}</a>
|
||||||
|
<a href="{% url 'assets:admin-user-delete' pk=admin_user.id %}" class="btn btn-xs btn-danger del">{% trans 'Delete' %}</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
{% endblock %}
|
|
@ -28,5 +28,10 @@ urlpatterns = [
|
||||||
url(r'^idc/(?P<pk>[0-9]+)$', views.IDCDetailView.as_view(), name='idc-detail'),
|
url(r'^idc/(?P<pk>[0-9]+)$', views.IDCDetailView.as_view(), name='idc-detail'),
|
||||||
url(r'^idc/(?P<pk>[0-9]+)/update', views.IDCUpdateView.as_view(), name='idc-update'),
|
url(r'^idc/(?P<pk>[0-9]+)/update', views.IDCUpdateView.as_view(), name='idc-update'),
|
||||||
url(r'^idc/(?P<pk>[0-9]+)/delete$', views.IDCDeleteView.as_view(), name='idc-delete'),
|
url(r'^idc/(?P<pk>[0-9]+)/delete$', views.IDCDeleteView.as_view(), name='idc-delete'),
|
||||||
|
url(r'^admin-user$', views.AdminUserListView.as_view(), name='admin-user-list'),
|
||||||
|
url(r'^admin-user/create$', views.AdminUserCreateView.as_view(), name='admin-user-create'),
|
||||||
|
url(r'^admin-user/(?P<pk>[0-9]+)$', views.AdminUserDetailView.as_view(), name='admin-user-detail'),
|
||||||
|
url(r'^admin-user/(?P<pk>[0-9]+)/update', views.AdminUserUpdateView.as_view(), name='admin-user-update'),
|
||||||
|
url(r'^admin-user/(?P<pk>[0-9]+)/delete$', views.AdminUserDeleteView.as_view(), name='admin-user-delete'),
|
||||||
# url(r'^api/v1.0/', include(router.urls)),
|
# url(r'^api/v1.0/', include(router.urls)),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,23 +1,4 @@
|
||||||
# ~*~ coding: utf-8 ~*~
|
# ~*~ coding: utf-8 ~*~
|
||||||
#
|
#
|
||||||
|
|
||||||
from django.contrib.auth.mixins import UserPassesTestMixin
|
|
||||||
from django.urls import reverse_lazy
|
|
||||||
|
|
||||||
from common.tasks import send_mail_async
|
|
||||||
from common.utils import reverse
|
|
||||||
from users.models import User
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
import cStringIO as StringIO
|
|
||||||
except ImportError:
|
|
||||||
import StringIO
|
|
||||||
|
|
||||||
|
|
||||||
class AdminUserRequiredMixin(UserPassesTestMixin):
|
|
||||||
login_url = reverse_lazy('users:login')
|
|
||||||
|
|
||||||
def test_func(self):
|
|
||||||
return self.request.user.is_staff
|
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,9 @@ from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateVi
|
||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
from django.views.generic.detail import DetailView, SingleObjectMixin
|
from django.views.generic.detail import DetailView, SingleObjectMixin
|
||||||
|
|
||||||
from .models import Asset, AssetGroup, IDC, AssetExtend
|
from .models import Asset, AssetGroup, IDC, AssetExtend, AdminUser, SystemUser
|
||||||
from .forms import AssetForm, AssetGroupForm, IDCForm
|
from .forms import AssetForm, AssetGroupForm, IDCForm
|
||||||
from .utils import AdminUserRequiredMixin
|
from .hands import AdminUserRequiredMixin
|
||||||
|
|
||||||
|
|
||||||
class AssetCreateView(CreateView):
|
class AssetCreateView(CreateView):
|
||||||
|
@ -50,7 +50,7 @@ class AssetDetailView(DetailView):
|
||||||
template_name = 'assets/asset_detail.html'
|
template_name = 'assets/asset_detail.html'
|
||||||
|
|
||||||
|
|
||||||
class AssetGroupCreateView(CreateView):
|
class AssetGroupCreateView(AdminUserRequiredMixin, CreateView):
|
||||||
model = AssetGroup
|
model = AssetGroup
|
||||||
form_class = AssetGroupForm
|
form_class = AssetGroupForm
|
||||||
template_name = 'assets/asset_group_create.html'
|
template_name = 'assets/asset_group_create.html'
|
||||||
|
@ -72,7 +72,7 @@ class AssetGroupCreateView(CreateView):
|
||||||
return super(AssetGroupCreateView, self).form_valid(form)
|
return super(AssetGroupCreateView, self).form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
class AssetGroupListView(ListView):
|
class AssetGroupListView(AdminUserRequiredMixin, ListView):
|
||||||
model = AssetGroup
|
model = AssetGroup
|
||||||
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
|
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
|
||||||
context_object_name = 'asset_group_list'
|
context_object_name = 'asset_group_list'
|
||||||
|
@ -101,7 +101,7 @@ class AssetGroupListView(ListView):
|
||||||
return self.queryset
|
return self.queryset
|
||||||
|
|
||||||
|
|
||||||
class AssetGroupDetailView(SingleObjectMixin, ListView):
|
class AssetGroupDetailView(SingleObjectMixin, AdminUserRequiredMixin, ListView):
|
||||||
template_name = 'assets/asset_group_detail.html'
|
template_name = 'assets/asset_group_detail.html'
|
||||||
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
|
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ class AssetGroupDetailView(SingleObjectMixin, ListView):
|
||||||
return super(AssetGroupDetailView, self).get_context_data(**kwargs)
|
return super(AssetGroupDetailView, self).get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class AssetGroupUpdateView(UpdateView):
|
class AssetGroupUpdateView(AdminUserRequiredMixin, UpdateView):
|
||||||
model = AssetGroup
|
model = AssetGroup
|
||||||
form_class = AssetGroupForm
|
form_class = AssetGroupForm
|
||||||
template_name = 'assets/asset_group_create.html'
|
template_name = 'assets/asset_group_create.html'
|
||||||
|
@ -138,13 +138,13 @@ class AssetGroupUpdateView(UpdateView):
|
||||||
return super(AssetGroupUpdateView, self).get_context_data(**kwargs)
|
return super(AssetGroupUpdateView, self).get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class AssetGroupDeleteView(DeleteView):
|
class AssetGroupDeleteView(AdminUserRequiredMixin, DeleteView):
|
||||||
template_name = 'assets/delete_confirm.html'
|
template_name = 'assets/delete_confirm.html'
|
||||||
model = AssetGroup
|
model = AssetGroup
|
||||||
success_url = reverse_lazy('assets:asset-group-list')
|
success_url = reverse_lazy('assets:asset-group-list')
|
||||||
|
|
||||||
|
|
||||||
class IDCListView(ListView):
|
class IDCListView(AdminUserRequiredMixin, ListView):
|
||||||
model = IDC
|
model = IDC
|
||||||
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
|
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
|
||||||
context_object_name = 'idc_list'
|
context_object_name = 'idc_list'
|
||||||
|
@ -173,7 +173,7 @@ class IDCListView(ListView):
|
||||||
return self.queryset
|
return self.queryset
|
||||||
|
|
||||||
|
|
||||||
class IDCCreateView(CreateView):
|
class IDCCreateView(AdminUserRequiredMixin, CreateView):
|
||||||
model = IDC
|
model = IDC
|
||||||
form_class = IDCForm
|
form_class = IDCForm
|
||||||
template_name = 'assets/idc_create.html'
|
template_name = 'assets/idc_create.html'
|
||||||
|
@ -188,13 +188,59 @@ class IDCCreateView(CreateView):
|
||||||
return super(IDCCreateView, self).get_context_data(**kwargs)
|
return super(IDCCreateView, self).get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
class IDCUpdateView(UpdateView):
|
class IDCUpdateView(AdminUserRequiredMixin, UpdateView):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class IDCDetailView(DetailView):
|
class IDCDetailView(AdminUserRequiredMixin, DetailView):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class IDCDeleteView(DeleteView):
|
class IDCDeleteView(AdminUserRequiredMixin, DeleteView):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class AdminUserListView(AdminUserRequiredMixin, ListView):
|
||||||
|
model = AdminUser
|
||||||
|
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE
|
||||||
|
context_object_name = 'admin_user_list'
|
||||||
|
template_name = 'assets/admin_user_list.html'
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = {
|
||||||
|
'app': _('Assets'),
|
||||||
|
'action': _('Admin user list'),
|
||||||
|
'keyword': self.request.GET.get('keyword', '')
|
||||||
|
}
|
||||||
|
kwargs.update(context)
|
||||||
|
return super(AdminUserListView, self).get_context_data(**kwargs)
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
# Todo: Default group by lose asset connection num
|
||||||
|
self.queryset = super(AdminUserListView, self).get_queryset()
|
||||||
|
self.keyword = keyword = self.request.GET.get('keyword', '')
|
||||||
|
self.sort = sort = self.request.GET.get('sort', '-date_created')
|
||||||
|
|
||||||
|
if keyword:
|
||||||
|
self.queryset = self.queryset.filter(Q(name__icontains=keyword) |
|
||||||
|
Q(comment__icontains=keyword))
|
||||||
|
|
||||||
|
if sort:
|
||||||
|
self.queryset = self.queryset.order_by(sort)
|
||||||
|
return self.queryset
|
||||||
|
|
||||||
|
|
||||||
|
class AdminUserCreateView(AdminUserRequiredMixin, CreateView):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class AdminUserUpdateView(AdminUserRequiredMixin, UpdateView):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class AdminUserDetailView(AdminUserRequiredMixin, DetailView):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class AdminUserDeleteView(AdminUserRequiredMixin, DeleteView):
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -5,6 +5,7 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.shortcuts import reverse as dj_reverse
|
from django.shortcuts import reverse as dj_reverse
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.core import signing
|
||||||
|
|
||||||
|
|
||||||
def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None, external=False):
|
def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None, external=False):
|
||||||
|
@ -21,3 +22,12 @@ def get_object_or_none(model, **kwargs):
|
||||||
except model.DoesNotExist:
|
except model.DoesNotExist:
|
||||||
obj = None
|
obj = None
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
def encrypt(*args, **kwargs):
|
||||||
|
return signing.dumps(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def decrypt(*args, **kwargs):
|
||||||
|
return signing.loads(*args, **kwargs)
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<li id="asset"><a href="{% url 'assets:asset-list' %}">{% trans 'Asset' %}</a></li>
|
<li id="asset"><a href="{% url 'assets:asset-list' %}">{% trans 'Asset' %}</a></li>
|
||||||
<li id="asset-group"><a href="{% url 'assets:asset-group-list' %}">{% trans 'Asset group' %}</a></li>
|
<li id="asset-group"><a href="{% url 'assets:asset-group-list' %}">{% trans 'Asset group' %}</a></li>
|
||||||
<li id="idc"><a href="{% url 'assets:idc-list' %}">{% trans 'IDC' %}</a></li>
|
<li id="idc"><a href="{% url 'assets:idc-list' %}">{% trans 'IDC' %}</a></li>
|
||||||
<li id="admin-user"><a href="">{% trans 'Admin user' %}</a></li>
|
<li id="admin-user"><a href="{% url 'assets:admin-user-list' %}">{% trans 'Admin user' %}</a></li>
|
||||||
<li id="system-user"><a href="">{% trans 'System user' %}</a></li>
|
<li id="system-user"><a href="">{% trans 'System user' %}</a></li>
|
||||||
<li id=""><a href="">{% trans 'Label' %}</a></li>
|
<li id=""><a href="">{% trans 'Label' %}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -30,10 +30,10 @@
|
||||||
<a href="#"><i class="fa fa-edit"></i> <span class="nav-label">{% trans 'Perms' %}</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 id="sudo">
|
<li id="sudo">
|
||||||
<a class="sudo" href="">{% trans 'Perm' %}</a>
|
<a class="sudo" href="">{% trans 'User perm' %}</a>
|
||||||
</li>
|
</li>
|
||||||
<li id="role">
|
<li id="role">
|
||||||
<a href="">{% trans 'Create perm' %}</a>
|
<a href="">{% trans 'User group perm' %}</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -14,46 +14,9 @@ from django.dispatch import receiver
|
||||||
from django.db import IntegrityError
|
from django.db import IntegrityError
|
||||||
from django.utils.translation import ugettext_lazy as _
|
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
|
||||||
|
|
||||||
# class Role(models.Model):
|
from common.utils import encrypt, decrypt
|
||||||
# name = models.CharField('name', max_length=80, unique=True)
|
|
||||||
# permissions = models.ManyToManyField(
|
|
||||||
# Permission,
|
|
||||||
# verbose_name='permissions',
|
|
||||||
# blank=True,
|
|
||||||
# )
|
|
||||||
# date_created = models.DateTimeField(auto_now_add=True)
|
|
||||||
# created_by = models.CharField(max_length=100)
|
|
||||||
# comment = models.CharField(max_length=80, blank=True)
|
|
||||||
#
|
|
||||||
# def __unicode__(self):
|
|
||||||
# return self.name
|
|
||||||
#
|
|
||||||
# def delete(self, using=None, keep_parents=False):
|
|
||||||
# if self.users.all().count() > 0:
|
|
||||||
# raise OperationalError('Role %s has some member, should not be delete.' % self.name)
|
|
||||||
# else:
|
|
||||||
# return super(Role, self).delete(using=using, keep_parents=keep_parents)
|
|
||||||
#
|
|
||||||
# class Meta:
|
|
||||||
# db_table = 'role'
|
|
||||||
#
|
|
||||||
# @classmethod
|
|
||||||
# def initial(cls):
|
|
||||||
# roles = {
|
|
||||||
# 'Administrator': {'permissions': Permission.objects.all(), 'comment': '管理员'},
|
|
||||||
# 'User': {'permissions': [], 'comment': '用户'},
|
|
||||||
# 'Auditor': {'permissions': Permission.objects.filter(content_type__app_label='audits'),
|
|
||||||
# 'comment': '审计员'},
|
|
||||||
# }
|
|
||||||
|
|
||||||
# for role_name, props in roles.items():
|
|
||||||
# if not cls.objects.filter(name=role_name):
|
|
||||||
# role = cls.objects.create(name=role_name, comment=props.get('comment', ''), created_by='System')
|
|
||||||
# if props.get('permissions'):
|
|
||||||
# role.permissions = props.get('permissions')
|
|
||||||
|
|
||||||
|
|
||||||
class UserGroup(models.Model):
|
class UserGroup(models.Model):
|
||||||
|
@ -65,6 +28,11 @@ class UserGroup(models.Model):
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
|
def has_member(self, user):
|
||||||
|
if user in self.users.all():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = 'user-group'
|
db_table = 'user-group'
|
||||||
|
|
||||||
|
@ -113,8 +81,8 @@ class User(AbstractUser):
|
||||||
phone = models.CharField(max_length=20, blank=True, verbose_name=_('Phone'))
|
phone = models.CharField(max_length=20, blank=True, verbose_name=_('Phone'))
|
||||||
enable_otp = models.BooleanField(default=False, verbose_name=_('Enable OTP'))
|
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 private key'))
|
_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=_('ssh public key'))
|
_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'))
|
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,
|
date_expired = models.DateTimeField(default=date_expired_default, blank=True, null=True,
|
||||||
|
@ -131,8 +99,8 @@ class User(AbstractUser):
|
||||||
#: user = User(username='example', ...)
|
#: user = User(username='example', ...)
|
||||||
#: user.set_password('password')
|
#: user.set_password('password')
|
||||||
@password_raw.setter
|
@password_raw.setter
|
||||||
def password_raw(self, raw_password):
|
def password_raw(self, password_raw_):
|
||||||
self.set_password(raw_password)
|
self.set_password(password_raw_)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_expired(self):
|
def is_expired(self):
|
||||||
|
@ -141,6 +109,22 @@ class User(AbstractUser):
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def private_key(self):
|
||||||
|
return decrypt(self._private_key)
|
||||||
|
|
||||||
|
@private_key.setter
|
||||||
|
def private_key(self, private_key_raw):
|
||||||
|
self._private_key = encrypt(private_key_raw)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def public_key(self):
|
||||||
|
return decrypt(self._public_key)
|
||||||
|
|
||||||
|
@public_key.setter
|
||||||
|
def public_key(self, public_key_raw):
|
||||||
|
self._public_key = encrypt(public_key_raw)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_superuser(self):
|
def is_superuser(self):
|
||||||
if self.role == 'Admin':
|
if self.role == 'Admin':
|
||||||
|
@ -198,6 +182,11 @@ class User(AbstractUser):
|
||||||
def generate_reset_token(self):
|
def generate_reset_token(self):
|
||||||
return signing.dumps({'reset': self.id, 'email': self.email})
|
return signing.dumps({'reset': self.id, 'email': self.email})
|
||||||
|
|
||||||
|
def is_member_of(self, user_group):
|
||||||
|
if user_group in self.groups.all():
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate_reset_token(cls, token, max_age=3600):
|
def validate_reset_token(cls, token, max_age=3600):
|
||||||
try:
|
try:
|
||||||
|
|
Loading…
Reference in New Issue