forked from shaba/openuds
added mfaData to admin
This commit is contained in:
parent
8783db925f
commit
1c65722d24
@ -80,21 +80,21 @@ class Users(DetailHandler):
|
||||
|
||||
custom_methods = ['servicesPools', 'userServices']
|
||||
|
||||
@staticmethod
|
||||
def uuid_to_id(iterator):
|
||||
for v in iterator:
|
||||
v['id'] = v['uuid']
|
||||
del v['uuid']
|
||||
yield v
|
||||
|
||||
def getItems(self, parent: Authenticator, item: typing.Optional[str]):
|
||||
# processes item to change uuid key for id
|
||||
def uuid_to_id(iterable: typing.Iterable[typing.MutableMapping[str, typing.Any]]):
|
||||
for v in iterable:
|
||||
v['id'] = v['uuid']
|
||||
del v['uuid']
|
||||
yield v
|
||||
|
||||
logger.debug(item)
|
||||
# Extract authenticator
|
||||
try:
|
||||
if item is None:
|
||||
values = list(
|
||||
Users.uuid_to_id(
|
||||
parent.users.all().values(
|
||||
uuid_to_id(
|
||||
(i for i in parent.users.all().values(
|
||||
'uuid',
|
||||
'name',
|
||||
'real_name',
|
||||
@ -104,7 +104,8 @@ class Users(DetailHandler):
|
||||
'is_admin',
|
||||
'last_access',
|
||||
'parent',
|
||||
)
|
||||
'mfaData',
|
||||
))
|
||||
)
|
||||
)
|
||||
for res in values:
|
||||
@ -127,6 +128,7 @@ class Users(DetailHandler):
|
||||
'is_admin',
|
||||
'last_access',
|
||||
'parent',
|
||||
'mfaData',
|
||||
),
|
||||
)
|
||||
res['id'] = u.uuid
|
||||
@ -153,7 +155,7 @@ class Users(DetailHandler):
|
||||
except Exception:
|
||||
return _('Current users')
|
||||
|
||||
def getFields(self, parent):
|
||||
def getFields(self, parent: Authenticator):
|
||||
return [
|
||||
{
|
||||
'name': {
|
||||
@ -198,12 +200,16 @@ class Users(DetailHandler):
|
||||
'staff_member',
|
||||
'is_admin',
|
||||
]
|
||||
if self._params.get('name', '') == '':
|
||||
if self._params.get('name', '').strip() == '':
|
||||
raise RequestError(_('Username cannot be empty'))
|
||||
|
||||
if 'password' in self._params:
|
||||
valid_fields.append('password')
|
||||
self._params['password'] = cryptoManager().hash(self._params['password'])
|
||||
|
||||
if 'mfaData' in self._params:
|
||||
valid_fields.append('mfaData')
|
||||
self._params['mfaData'] = self._params['mfaData'].strip()
|
||||
|
||||
fields = self.readFieldsFromParams(valid_fields)
|
||||
if not self._user.is_admin:
|
||||
@ -224,9 +230,8 @@ class Users(DetailHandler):
|
||||
user.__dict__.update(fields)
|
||||
|
||||
logger.debug('User parent: %s', user.parent)
|
||||
if auth.isExternalSource is False and (
|
||||
user.parent is None or user.parent == ''
|
||||
):
|
||||
# If internal auth, threat it "special"
|
||||
if auth.isExternalSource is False and not user.parent:
|
||||
groups = self.readFieldsFromParams(['groups'])['groups']
|
||||
logger.debug('Groups: %s', groups)
|
||||
logger.debug('Got Groups %s', parent.groups.filter(uuid__in=groups))
|
||||
@ -414,7 +419,7 @@ class Groups(DetailHandler):
|
||||
except Exception:
|
||||
raise self.invalidRequestException()
|
||||
|
||||
def saveItem(self, parent: Authenticator, item) -> None:
|
||||
def saveItem(self, parent: Authenticator, item: typing.Optional[str]) -> None:
|
||||
group = None # Avoid warning on reference before assignment
|
||||
try:
|
||||
is_meta = self._params['type'] == 'meta'
|
||||
@ -429,7 +434,7 @@ class Groups(DetailHandler):
|
||||
fields = self.readFieldsFromParams(valid_fields)
|
||||
is_pattern = fields.get('name', '').find('pat:') == 0
|
||||
auth = parent.getInstance()
|
||||
if item is None: # Create new
|
||||
if not item: # Create new
|
||||
if not is_meta and not is_pattern:
|
||||
auth.createGroup(
|
||||
fields
|
||||
@ -482,7 +487,9 @@ class Groups(DetailHandler):
|
||||
except Exception:
|
||||
raise self.invalidItemException()
|
||||
|
||||
def servicesPools(self, parent: Authenticator, item: str) -> typing.List[typing.Mapping[str, typing.Any]]:
|
||||
def servicesPools(
|
||||
self, parent: Authenticator, item: str
|
||||
) -> typing.List[typing.Mapping[str, typing.Any]]:
|
||||
uuid = processUuid(item)
|
||||
group = parent.groups.get(uuid=processUuid(uuid))
|
||||
res: typing.List[typing.Mapping[str, typing.Any]] = []
|
||||
@ -503,7 +510,9 @@ class Groups(DetailHandler):
|
||||
|
||||
return res
|
||||
|
||||
def users(self, parent: Authenticator, item: str) -> typing.List[typing.Mapping[str, typing.Any]]:
|
||||
def users(
|
||||
self, parent: Authenticator, item: str
|
||||
) -> typing.List[typing.Mapping[str, typing.Any]]:
|
||||
uuid = processUuid(item)
|
||||
group = parent.groups.get(uuid=processUuid(uuid))
|
||||
|
||||
|
@ -99,7 +99,7 @@ class InternalDBAuth(auths.Authenticator):
|
||||
if self.reverseDns.isTrue():
|
||||
try:
|
||||
return str(
|
||||
dns.resolver.query(dns.reversename.from_address(ip), 'PTR')[0]
|
||||
dns.resolver.query(dns.reversename.from_address(ip).to_text(), 'PTR')[0]
|
||||
)
|
||||
except Exception:
|
||||
pass
|
||||
|
@ -178,6 +178,9 @@ class StorageAsDict(MutableMapping):
|
||||
def get(self, key: str, default: typing.Any = None) -> typing.Any:
|
||||
return self[key] or default
|
||||
|
||||
def delete(self, key: str) -> None:
|
||||
self.__delitem__(key)
|
||||
|
||||
# Custom utility methods
|
||||
@property
|
||||
def group(self) -> str:
|
||||
|
@ -1,4 +1,4 @@
|
||||
# Generated by Django 3.2.10 on 2022-06-23 19:34
|
||||
# Generated by Django 3.2.10 on 2022-07-04 21:20
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
@ -11,6 +11,11 @@ class Migration(migrations.Migration):
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='user',
|
||||
name='mfaData',
|
||||
field=models.CharField(default='', max_length=128),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='MFA',
|
||||
fields=[
|
@ -37,6 +37,7 @@ from django.db import models
|
||||
from django.db.models import signals, Q, Count
|
||||
|
||||
from uds.core.util import log
|
||||
from uds.core.util import storage
|
||||
|
||||
from .authenticator import Authenticator
|
||||
from .util import UnsavedForeignKey
|
||||
@ -67,6 +68,9 @@ class User(UUIDModel):
|
||||
state = models.CharField(max_length=1, db_index=True)
|
||||
password = models.CharField(
|
||||
max_length=128, default=''
|
||||
) # Only used on "internal" sources or sources that "needs password"
|
||||
mfaData = models.CharField(
|
||||
max_length=128, default=''
|
||||
) # Only used on "internal" sources
|
||||
staff_member = models.BooleanField(
|
||||
default=False
|
||||
@ -202,6 +206,26 @@ class User(UUIDModel):
|
||||
# This group matches
|
||||
yield g
|
||||
|
||||
# Get custom data
|
||||
def getCustomData(self, key: str) -> typing.Optional[str]:
|
||||
"""
|
||||
Returns the custom data for this user for the provided key.
|
||||
|
||||
Usually custom data will be associated with transports, but can be custom data registered by ANY module.
|
||||
|
||||
Args:
|
||||
key: key of the custom data to get
|
||||
|
||||
Returns:
|
||||
|
||||
The custom data for the key specified as a string (can be empty if key is not found).
|
||||
|
||||
If the key exists, the custom data will always contain something, but may be the values are the default ones.
|
||||
|
||||
"""
|
||||
with storage.StorageAccess('manager' + self.manager.uuid) as store:
|
||||
return store[self.uuid + '_' + key]
|
||||
|
||||
def __str__(self):
|
||||
return 'User {} (id:{}) from auth {}'.format(
|
||||
self.name, self.id, self.manager.name
|
||||
@ -217,11 +241,15 @@ class User(UUIDModel):
|
||||
|
||||
:note: If destroy raises an exception, the deletion is not taken.
|
||||
"""
|
||||
toDelete = kwargs['instance']
|
||||
toDelete: User = kwargs['instance']
|
||||
|
||||
# first, we invoke removeUser. If this raises an exception, user will not
|
||||
# be removed
|
||||
toDelete.getManager().removeUser(toDelete.name)
|
||||
# Remove related stored values
|
||||
with storage.StorageAccess('manager' + toDelete.manager.uuid) as store:
|
||||
for key in store.keys():
|
||||
store.delete(key)
|
||||
|
||||
# now removes all "child" of this user, if it has children
|
||||
User.objects.filter(parent=toDelete.id).delete()
|
||||
|
@ -98,7 +98,7 @@ class UserService(UUIDModel): # pylint: disable=too-many-public-methods
|
||||
state_date = models.DateTimeField(db_index=True)
|
||||
creation_date = models.DateTimeField(db_index=True)
|
||||
data = models.TextField(default='')
|
||||
user: 'models.ForeignKey[UserService, User]' = models.ForeignKey(
|
||||
user = models.ForeignKey(
|
||||
User,
|
||||
on_delete=models.CASCADE,
|
||||
related_name='userServices',
|
||||
@ -394,7 +394,7 @@ class UserService(UUIDModel): # pylint: disable=too-many-public-methods
|
||||
self.os_state = state
|
||||
self.save(update_fields=['os_state', 'state_date'])
|
||||
|
||||
def assignToUser(self, user: User) -> None:
|
||||
def assignToUser(self, user: typing.Optional[User]) -> None:
|
||||
"""
|
||||
Assigns this user deployed service to an user.
|
||||
|
||||
@ -403,7 +403,7 @@ class UserService(UUIDModel): # pylint: disable=too-many-public-methods
|
||||
"""
|
||||
self.cache_level = 0
|
||||
self.state_date = getSqlDatetime()
|
||||
self.user = user # type: ignore
|
||||
self.user = user
|
||||
self.save(update_fields=['cache_level', 'state_date', 'user'])
|
||||
|
||||
def setInUse(self, inUse: bool) -> None:
|
||||
|
File diff suppressed because one or more lines are too long
@ -487,6 +487,7 @@ gettext("Role");
|
||||
gettext("Admin");
|
||||
gettext("Staff member");
|
||||
gettext("User");
|
||||
gettext("MFA");
|
||||
gettext("Groups");
|
||||
gettext("Cancel");
|
||||
gettext("Ok");
|
||||
|
@ -99,7 +99,7 @@
|
||||
</svg>
|
||||
</div>
|
||||
</uds-root>
|
||||
<script src="/uds/res/admin/runtime.js?stamp=1656004218" defer></script><script src="/uds/res/admin/polyfills-es5.js?stamp=1656004218" nomodule defer></script><script src="/uds/res/admin/polyfills.js?stamp=1656004218" defer></script><script src="/uds/res/admin/main.js?stamp=1656004218" defer></script>
|
||||
<script src="/uds/res/admin/runtime.js?stamp=1656962877" defer></script><script src="/uds/res/admin/polyfills-es5.js?stamp=1656962877" nomodule defer></script><script src="/uds/res/admin/polyfills.js?stamp=1656962877" defer></script><script src="/uds/res/admin/main.js?stamp=1656962877" defer></script>
|
||||
|
||||
|
||||
</body></html>
|
Loading…
Reference in New Issue
Block a user