Commit 69f2bf66 authored by ibuler's avatar ibuler

Finish user permission revoke

parent dde9ffb2
...@@ -32,7 +32,7 @@ $(document).ready(function(){ ...@@ -32,7 +32,7 @@ $(document).ready(function(){
ele: $('#admin_user_list_table'), ele: $('#admin_user_list_table'),
columnDefs: [ columnDefs: [
{targets: 1, createdCell: function (td, cellData, rowData) { {targets: 1, createdCell: function (td, cellData, rowData) {
var detail_btn = '<a href="{% url "assets:api-admin-user-detail" pk=99991937 %}">' + cellData + '</a>'; var detail_btn = '<a href="{% url "assets:admin-user-detail" pk=99991937 %}">' + cellData + '</a>';
$(td).html(detail_btn.replace('99991937', rowData.id)); $(td).html(detail_btn.replace('99991937', rowData.id));
}}, }},
{targets: 5, createdCell: function (td, cellData) { {targets: 5, createdCell: function (td, cellData) {
......
...@@ -248,4 +248,11 @@ def validate_ssh_public_key(text): ...@@ -248,4 +248,11 @@ def validate_ssh_public_key(text):
return True return True
def setattr_bulk(seq, key, value):
def set_attr(obj):
setattr(obj, key, value)
return obj
return map(set_attr, seq)
signer = Signer() signer = Signer()
\ No newline at end of file
...@@ -5,8 +5,10 @@ from rest_framework.views import APIView, Response ...@@ -5,8 +5,10 @@ from rest_framework.views import APIView, Response
from rest_framework.generics import ListCreateAPIView from rest_framework.generics import ListCreateAPIView
from rest_framework import viewsets from rest_framework import viewsets
from users.backends import IsValidUser, IsSuperUser from users.backends import IsValidUser, IsSuperUser
from .utils import get_user_granted_assets, get_user_granted_asset_groups from common.utils import get_object_or_none
from .utils import get_user_granted_assets, get_user_granted_asset_groups, get_user_asset_permissions
from .models import AssetPermission from .models import AssetPermission
from .hands import User
from . import serializers from . import serializers
...@@ -18,11 +20,41 @@ class AssetPermissionViewSet(viewsets.ModelViewSet): ...@@ -18,11 +20,41 @@ class AssetPermissionViewSet(viewsets.ModelViewSet):
def get_queryset(self): def get_queryset(self):
queryset = super(AssetPermissionViewSet, self).get_queryset() queryset = super(AssetPermissionViewSet, self).get_queryset()
user_id = self.request.query_params.get('user', '') user_id = self.request.query_params.get('user', '')
if user_id: if user_id and user_id.isdigit():
queryset = queryset.filter(users__id=user_id) from users.models import User
self.user_id = user_id
user = get_object_or_none(User, id=int(user_id))
if user:
queryset = get_user_asset_permissions(user)
print(queryset)
return queryset return queryset
def get_serializer_class(self):
if getattr(self, 'user_id', ''):
return serializers.UserAssetPermissionSerializer
return serializers.AssetPermissionSerializer
class RevokeUserAssetPermission(APIView):
permission_classes = (IsSuperUser,)
def put(self, request, *args, **kwargs):
permission_id = str(request.data.get('id', ''))
user_id = str(request.data.get('user_id', ''))
if permission_id and user_id and permission_id.isdigit() and user_id.isdigit():
permission_id = int(permission_id)
user_id = int(user_id)
asset_permission = get_object_or_none(AssetPermission, id=permission_id)
user = get_object_or_none(User, id=user_id)
print(asset_permission)
print(user)
if asset_permission and user:
asset_permission.users.remove(user)
return Response({'msg': 'success'})
return Response({'msg': 'failed'}, status=404)
class UserAssetsApi(APIView): class UserAssetsApi(APIView):
permission_classes = (IsValidUser,) permission_classes = (IsValidUser,)
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from rest_framework import serializers from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
from common.utils import get_object_or_none
from .models import AssetPermission from .models import AssetPermission
from .hands import User
class AssetPermissionSerializer(serializers.ModelSerializer): class AssetPermissionSerializer(serializers.ModelSerializer):
# users_amount = serializers.SerializerMethodField()
# user_groups_amount = serializers.SerializerMethodField()
# assets_amount = serializers.SerializerMethodField()
# asset_groups_amount = serializers.SerializerMethodField()
class Meta: class Meta:
model = AssetPermission model = AssetPermission
fields = ['id', 'name', 'users', 'user_groups', 'assets', 'asset_groups',
'system_users', 'is_active', 'comment', 'date_expired']
class UserAssetPermissionSerializer(AssetPermissionSerializer):
# @staticmethod is_inherited = serializers.SerializerMethodField()
# def get_users_amount(obj):
# return obj.users.count() @staticmethod
# def get_is_inherited(obj):
# @staticmethod if getattr(obj, 'inherited', ''):
# def get_user_groups_amount(obj): return True
# return obj.user_groups.count() else:
# return False
# @staticmethod
# def get_assets_amount(obj):
# return obj.assets.count()
#
# @staticmethod
# def get_asset_groups_amount(obj):
# return obj.asset_groups.count()
...@@ -26,10 +26,10 @@ router = routers.DefaultRouter() ...@@ -26,10 +26,10 @@ router = routers.DefaultRouter()
router.register('v1/asset-permissions', api.AssetPermissionViewSet, 'api-asset-permission') router.register('v1/asset-permissions', api.AssetPermissionViewSet, 'api-asset-permission')
urlpatterns += [ urlpatterns += [
url(r'^v1/user/assets/$', api.UserAssetsApi.as_view(), url(r'^v1/user/assets/$', api.UserAssetsApi.as_view(), name='user-assets'),
name='user-assets'), url(r'^v1/asset-permissions/user/revoke/', api.RevokeUserAssetPermission.as_view(),
url(r'^v1/user/asset-groups/$', api.UserAssetsGroupsApi.as_view(), name='revoke-user-asset-permission'),
name='user-asset-groups'), url(r'^v1/user/asset-groups/$', api.UserAssetsGroupsApi.as_view(), name='user-asset-groups'),
url(r'^v1/user/asset-groups/(?P<pk>[0-9]+)/assets/$', api.UserAssetsGroupAssetsApi.as_view(), url(r'^v1/user/asset-groups/(?P<pk>[0-9]+)/assets/$', api.UserAssetsGroupAssetsApi.as_view(),
name='user-asset-groups-assets'), name='user-asset-groups-assets'),
] ]
......
from __future__ import absolute_import, unicode_literals from __future__ import absolute_import, unicode_literals
from common.utils import setattr_bulk
from .hands import User, UserGroup, Asset, AssetGroup, SystemUser from .hands import User, UserGroup, Asset, AssetGroup, SystemUser
...@@ -7,7 +8,7 @@ def get_user_group_granted_asset_groups(user_group): ...@@ -7,7 +8,7 @@ def get_user_group_granted_asset_groups(user_group):
"""Return asset groups granted of the user group """Return asset groups granted of the user group
:param user_group: Instance of :class: ``UserGroup`` :param user_group: Instance of :class: ``UserGroup``
:return: {asset1: {system_user1, }, asset1: {system_user1, system_user2]} :return: {asset_group1: {system_user1, }, asset_group2: {system_user1, system_user2]}
""" """
asset_groups = {} asset_groups = {}
asset_permissions = user_group.asset_permissions.all() asset_permissions = user_group.asset_permissions.all()
...@@ -41,7 +42,6 @@ def get_user_group_granted_assets(user_group): ...@@ -41,7 +42,6 @@ def get_user_group_granted_assets(user_group):
assets[asset] |= set(asset_permission.system_users.all()) assets[asset] |= set(asset_permission.system_users.all())
else: else:
assets[asset] = set(asset_permission.system_users.all()) assets[asset] = set(asset_permission.system_users.all())
return assets return assets
...@@ -112,7 +112,6 @@ def get_user_granted_asset_groups(user): ...@@ -112,7 +112,6 @@ def get_user_granted_asset_groups(user):
asset_groups[asset_group] |= asset_groups_direct[asset_group] asset_groups[asset_group] |= asset_groups_direct[asset_group]
else: else:
asset_groups[asset_group] = asset_groups_direct[asset_group] asset_groups[asset_group] = asset_groups_direct[asset_group]
return asset_groups return asset_groups
...@@ -175,10 +174,25 @@ def get_user_granted_assets(user): ...@@ -175,10 +174,25 @@ def get_user_granted_assets(user):
assets[asset] |= assets_direct[asset] assets[asset] |= assets_direct[asset]
else: else:
assets[asset] = assets_direct[asset] assets[asset] = assets_direct[asset]
return assets return assets
def get_user_group_asset_permissions(user_group):
permissions = user_group.asset_permissions.all()
return permissions
def get_user_asset_permissions(user):
user_group_permissions = set()
direct_permissions = set(setattr_bulk(user.asset_permissions.all(), 'inherited', 0))
for user_group in user.groups.all():
permissions = get_user_group_asset_permissions(user_group)
user_group_permissions |= set(permissions)
user_group_permissions = set(setattr_bulk(user_group_permissions, 'inherited', 1))
return direct_permissions | user_group_permissions
def get_user_groups_granted_in_asset(asset): def get_user_groups_granted_in_asset(asset):
pass pass
......
...@@ -198,19 +198,18 @@ function APIUpdateAttr(props) { ...@@ -198,19 +198,18 @@ function APIUpdateAttr(props) {
contentType: props.content_type || "application/json; charset=utf-8", contentType: props.content_type || "application/json; charset=utf-8",
dataType: props.data_type || "json" dataType: props.data_type || "json"
}).done(function(data, textStatue, jqXHR) { }).done(function(data, textStatue, jqXHR) {
toastr.success(success_message);
if (typeof props.success === 'function') { if (typeof props.success === 'function') {
return props.success(data); return props.success(data);
} else { }
toastr.success(success_message);
}
}).fail(function(jqXHR, textStatue, errorThrown) { }).fail(function(jqXHR, textStatue, errorThrown) {
toastr.error(fail_message);
if (typeof props.error === 'function') { if (typeof props.error === 'function') {
return props.error(errorThrown); return props.error(errorThrown);
} else { }
toastr.error(textStatue);
}
}); });
return true; // return true;
} }
// Sweet Alert for Delete // Sweet Alert for Delete
......
...@@ -6,8 +6,8 @@ from django.utils.translation import gettext_lazy as _ ...@@ -6,8 +6,8 @@ from django.utils.translation import gettext_lazy as _
from captcha.fields import CaptchaField from captcha.fields import CaptchaField
from common.utils import validate_ssh_public_key from common.utils import validate_ssh_public_key
from perms.models import AssetPermission
from .models import User, UserGroup from .models import User, UserGroup
from .hands import AssetPermission
class UserLoginForm(AuthenticationForm): class UserLoginForm(AuthenticationForm):
...@@ -101,7 +101,7 @@ class UserPrivateAssetPermissionForm(forms.ModelForm): ...@@ -101,7 +101,7 @@ class UserPrivateAssetPermissionForm(forms.ModelForm):
def save(self, commit=True): def save(self, commit=True):
self.instance = super(UserPrivateAssetPermissionForm, self).save(commit=commit) self.instance = super(UserPrivateAssetPermissionForm, self).save(commit=commit)
# self.instance.private_for = 'U' self.instance.private_for = 'U'
self.instance.users = [self.user] self.instance.users = [self.user]
self.instance.save() self.instance.save()
return self.instance return self.instance
......
...@@ -11,5 +11,5 @@ ...@@ -11,5 +11,5 @@
""" """
from terminal.models import Terminal from terminal.models import Terminal
from perms.models import AssetPermission # from perms.models import AssetPermission
from perms.utils import get_user_granted_assets, get_user_granted_asset_groups # from perms.utils import get_user_granted_assets, get_user_granted_asset_groups
...@@ -313,7 +313,6 @@ $(document).ready(function() { ...@@ -313,7 +313,6 @@ $(document).ready(function() {
var user_groups = $('.bdg_user_group').map(function() { var user_groups = $('.bdg_user_group').map(function() {
return $(this).data('gid'); return $(this).data('gid');
}).get(); }).get();
console.log(user_groups);
updateUserGroups(user_groups) updateUserGroups(user_groups)
}).on('click', '#btn_reset_password', function() { }).on('click', '#btn_reset_password', function() {
function doReset() { function doReset() {
......
...@@ -53,7 +53,7 @@ $(document).ready(function(){ ...@@ -53,7 +53,7 @@ $(document).ready(function(){
$(td).html(detail_btn.replace('99991937', rowData.id)); $(td).html(detail_btn.replace('99991937', rowData.id));
}}, }},
{targets: 4, createdCell: function (td, cellData) { {targets: 4, createdCell: function (td, cellData) {
var innerHtml = cellData.length > 8 ? cellData.substring(0, 8) + '...': cellData; var innerHtml = cellData.length > 20 ? cellData.substring(0, 20) + '...': cellData;
$(td).html('<a href="javascript:void(0);" data-toggle="tooltip" title="' + cellData + '">' + innerHtml + '</a>'); $(td).html('<a href="javascript:void(0);" data-toggle="tooltip" title="' + cellData + '">' + innerHtml + '</a>');
}}, }},
{targets: 6, createdCell: function (td, cellData) { {targets: 6, createdCell: function (td, cellData) {
......
...@@ -19,13 +19,13 @@ urlpatterns = [ ...@@ -19,13 +19,13 @@ urlpatterns = [
url(r'^user/(?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'^user/(?P<pk>[0-9]+)/asset-permission$', views.UserAssetPermissionView.as_view(), url(r'^user/(?P<pk>[0-9]+)/asset-permission$', views.UserAssetPermissionView.as_view(),
name='user-asset-permission'), name='user-asset-permission'),
url(r'^user/(?P<pk>[0-9]+)/asset-permission/create$', views.UserAssetPermissionCreateView.as_view(), # url(r'^user/(?P<pk>[0-9]+)/asset-permission/create$', views.UserAssetPermissionCreateView.as_view(),
name='user-asset-permission-create'), # name='user-asset-permission-create'),
url(r'^user/(?P<pk>[0-9]+)/granted-asset', views.UserGrantedAssetView.as_view(), name='user-granted-asset'), url(r'^user/(?P<pk>[0-9]+)/granted-asset', views.UserGrantedAssetView.as_view(), name='user-granted-asset'),
url(r'^user/(?P<pk>[0-9]+)/login-history', views.UserDetailView.as_view(), name='user-login-history'), url(r'^user/(?P<pk>[0-9]+)/login-history', views.UserDetailView.as_view(), name='user-login-history'),
url(r'^first-login/$', views.UserFirstLoginView.as_view(), name='user-first-login'), url(r'^first-login/$', views.UserFirstLoginView.as_view(), name='user-first-login'),
url(r'^import/$', views.BulkImportUserView.as_view(), name='user-import'), url(r'^import/$', views.BulkImportUserView.as_view(), name='user-import'),
url(r'^user/(?P<pk>[0-9]+)/assets-perm$', views.UserDetailView.as_view(), name='user-detail'), # url(r'^user/(?P<pk>[0-9]+)/assets-perm$', views.UserDetailView.as_view(), name='user-detail'),
url(r'^user/create$', views.UserCreateView.as_view(), name='user-create'), url(r'^user/create$', views.UserCreateView.as_view(), name='user-create'),
url(r'^user/(?P<pk>[0-9]+)/update$', views.UserUpdateView.as_view(), name='user-update'), url(r'^user/(?P<pk>[0-9]+)/update$', views.UserUpdateView.as_view(), name='user-update'),
......
...@@ -120,60 +120,60 @@ def send_reset_ssh_key_mail(user): ...@@ -120,60 +120,60 @@ def send_reset_ssh_key_mail(user):
send_mail_async.delay(subject, message, recipient_list, html_message=message) send_mail_async.delay(subject, message, recipient_list, html_message=message)
def validate_ssh_pk(text): # def validate_ssh_pk(text):
""" # """
Expects a SSH private key as string. # Expects a SSH private key as string.
Returns a boolean and a error message. # Returns a boolean and a error message.
If the text is parsed as private key successfully, # If the text is parsed as private key successfully,
(True,'') is returned. Otherwise, # (True,'') is returned. Otherwise,
(False, <message describing the error>) is returned. # (False, <message describing the error>) is returned.
#
from https://github.com/githubnemo/SSH-private-key-validator/blob/master/validate.py # from https://github.com/githubnemo/SSH-private-key-validator/blob/master/validate.py
#
""" # """
#
if not text: # if not text:
return False, 'No text given' # return False, 'No text given'
#
startPattern = re.compile("^-----BEGIN [A-Z]+ PRIVATE KEY-----") # startPattern = re.compile("^-----BEGIN [A-Z]+ PRIVATE KEY-----")
optionPattern = re.compile("^.+: .+") # optionPattern = re.compile("^.+: .+")
contentPattern = re.compile("^([a-zA-Z0-9+/]{64}|[a-zA-Z0-9+/]{1,64}[=]{0,2})$") # contentPattern = re.compile("^([a-zA-Z0-9+/]{64}|[a-zA-Z0-9+/]{1,64}[=]{0,2})$")
endPattern = re.compile("^-----END [A-Z]+ PRIVATE KEY-----") # endPattern = re.compile("^-----END [A-Z]+ PRIVATE KEY-----")
#
def contentState(text): # def contentState(text):
for i in range(0, len(text)): # for i in range(0, len(text)):
line = text[i] # line = text[i]
#
if endPattern.match(line): # if endPattern.match(line):
if i == len(text) - 1 or len(text[i + 1]) == 0: # if i == len(text) - 1 or len(text[i + 1]) == 0:
return True, '' # return True, ''
else: # else:
return False, 'At end but content coming' # return False, 'At end but content coming'
#
elif not contentPattern.match(line): # elif not contentPattern.match(line):
return False, 'Wrong string in content section' # return False, 'Wrong string in content section'
#
return False, 'No content or missing end line' # return False, 'No content or missing end line'
#
def optionState(text): # def optionState(text):
for i in range(0, len(text)): # for i in range(0, len(text)):
line = text[i] # line = text[i]
#
if line[-1:] == '\\': # if line[-1:] == '\\':
return optionState(text[i + 2:]) # return optionState(text[i + 2:])
#
if not optionPattern.match(line): # if not optionPattern.match(line):
return contentState(text[i + 1:]) # return contentState(text[i + 1:])
#
return False, 'Expected option, found nothing' # return False, 'Expected option, found nothing'
def startState(text): # def startState(text):
if len(text) == 0 or not startPattern.match(text[0]): # if len(text) == 0 or not startPattern.match(text[0]):
return False, 'Header is wrong' # return False, 'Header is wrong'
return optionState(text[1:]) # return optionState(text[1:])
#
return startState([n.strip() for n in text.splitlines()]) # return startState([n.strip() for n in text.splitlines()])
#
def check_user_valid(**kwargs): def check_user_valid(**kwargs):
password = kwargs.pop('password', None) password = kwargs.pop('password', None)
......
...@@ -21,14 +21,14 @@ from django.views.generic.list import ListView ...@@ -21,14 +21,14 @@ from django.views.generic.list import ListView
from django.views.generic.edit import CreateView, DeleteView, UpdateView, FormView, SingleObjectMixin, \ from django.views.generic.edit import CreateView, DeleteView, UpdateView, FormView, SingleObjectMixin, \
FormMixin FormMixin
from django.views.generic.detail import DetailView from django.views.generic.detail import DetailView
from formtools.wizard.views import SessionWizardView from formtools.wizard.views import SessionWizardView
from common.mixins import JSONResponseMixin from common.mixins import JSONResponseMixin
from common.utils import get_object_or_none, get_logger from common.utils import get_object_or_none, get_logger
from perms.models import AssetPermission
from .models import User, UserGroup from .models import User, UserGroup
from .utils import AdminUserRequiredMixin, user_add_success_next, send_reset_password_mail from .utils import AdminUserRequiredMixin, user_add_success_next, send_reset_password_mail
from .hands import AssetPermission, get_user_granted_asset_groups, get_user_granted_assets # from .hands import AssetPermission, get_user_granted_asset_groups, get_user_granted_assets
from . import forms from . import forms
...@@ -341,32 +341,33 @@ class UserFirstLoginView(LoginRequiredMixin, SessionWizardView): ...@@ -341,32 +341,33 @@ class UserFirstLoginView(LoginRequiredMixin, SessionWizardView):
return form return form
class UserAssetPermissionView(AdminUserRequiredMixin, FormMixin, SingleObjectMixin, ListView): class UserAssetPermissionView(AdminUserRequiredMixin, DetailView):
paginate_by = settings.CONFIG.DISPLAY_PER_PAGE model = User
template_name = 'users/user_asset_permission.html' template_name = 'users/user_asset_permission.html'
context_object_name = 'user_object' context_object_name = 'user'
form_class = forms.UserPrivateAssetPermissionForm
# form_class = forms.UserPrivateAssetPermissionForm
def get(self, request, *args, **kwargs):
self.object = self.get_object(queryset=User.objects.all()) # def get(self, request, *args, **kwargs):
return super(UserAssetPermissionView, self).get(request, *args, **kwargs) # self.object = self.get_object(queryset=User.objects.all())
# return super(UserAssetPermissionView, self).get(request, *args, **kwargs)
def get_asset_permission_inherit_from_user_group(self):
asset_permissions = set() # def get_asset_permission_inherit_from_user_group(self):
user_groups = self.object.groups.all() # asset_permissions = set()
# user_groups = self.object.groups.all()
for user_group in user_groups: #
for asset_permission in user_group.asset_permissions.all(): # for user_group in user_groups:
setattr(asset_permission, 'is_inherit_from_user_groups', True) # for asset_permission in user_group.asset_permissions.all():
setattr(asset_permission, 'inherit_from_user_groups', # setattr(asset_permission, 'is_inherit_from_user_groups', True)
getattr(asset_permission, b'inherit_from_user_groups', set()).add(user_group)) # setattr(asset_permission, 'inherit_from_user_groups',
asset_permissions.add(asset_permission) # getattr(asset_permission, b'inherit_from_user_groups', set()).add(user_group))
return asset_permissions # asset_permissions.add(asset_permission)
# return asset_permissions
def get_queryset(self): #
asset_permissions = set(self.object.asset_permissions.all()) \ # def get_queryset(self):
| self.get_asset_permission_inherit_from_user_group() # asset_permissions = set(self.object.asset_permissions.all()) \
return list(asset_permissions) # | self.get_asset_permission_inherit_from_user_group()
# return list(asset_permissions)
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = { context = {
...@@ -414,18 +415,19 @@ class UserGrantedAssetView(AdminUserRequiredMixin, SingleObjectMixin, ListView): ...@@ -414,18 +415,19 @@ class UserGrantedAssetView(AdminUserRequiredMixin, SingleObjectMixin, ListView):
def get_queryset(self): def get_queryset(self):
# Convert format from {'asset': ['system_users'], ..} to # Convert format from {'asset': ['system_users'], ..} to
# [('asset', ['system_users']), ('asset', ['system_users'])) # [('asset', ['system_users']), ('asset', ['system_users']))
assets_granted = [(asset, system_users) for asset, system_users in # assets_granted = [(asset, system_users) for asset, system_users in
get_user_granted_assets(self.object).items()] # get_user_granted_assets(self.object).items()]
return assets_granted # return assets_granted
return []
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
asset_groups = [(asset_group, system_users) for asset_group, system_users in # asset_groups = [(asset_group, system_users) for asset_group, system_users in
get_user_granted_asset_groups(self.object).items()] # get_user_granted_asset_groups(self.object).items()]
context = { context = {
'app': 'User', 'app': 'User',
'action': 'User granted asset', 'action': 'User granted asset',
'asset_groups': asset_groups, # 'asset_groups': asset_groups,
} }
kwargs.update(context) kwargs.update(context)
return super(UserGrantedAssetView, self).get_context_data(**kwargs) return super(UserGrantedAssetView, self).get_context_data(**kwargs)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment