Джанго и CFR 21 часть 11
Я должен преобразовать свое приложение Django так, чтобы оно соответствовало " 21 CFR Part 11", то есть сделать электронные записи такими же, как подписанные бумажные записи. Есть ли какой-либо проект или приложение, на которое я должен посмотреть?
Некоторые вопросы:
- контрольный журнал: каждое изменение в выбранных моделях должно отслеживаться (кто, когда, что)
- обнаружение несанкционированного редактирования записи: если запись была изменена / добавлена / удалена за пределами обычной процедуры, приложение должно обнаружить ее
- для определенных операций пользователь должен снова ввести пароль
- пароли должны периодически меняться и должны соответствовать определенным критериям и т. д.
Я не нашел готового решения в сети...
2 ответа
Я работаю в среде, требующей CFR 21 Part 11 и аналогичных. Я еще не полностью совместил наши приложения, но я прошел через множество проб и ошибок, так что я могу помочь вам начать работу в нескольких местах.
1) Я бы также предложил возврат Джанго; однако вам потребуется немного больше, чем то, что он предлагает, чтобы получить контрольный журнал переменного уровня с выполненным действием (в дополнение к тому, кем и когда). Для этого я использовал один из сигналов возврата, чтобы превратить поле комментария в диктовку, которую можно было оценить, а затем вызвать любую переменную в строке и действие, которое было предпринято для нее и т. Д. Это ниже:
https://github.com/etianen/django-reversion
@receiver(reversion.pre_revision_commit)
def it_worked(sender, **kwargs):
currentVersion = kwargs.pop('versions')[0].field_dict
fieldList = currentVersion.keys()
fieldList.remove('id')
commentDict = {}
try:
pastVersion = reversion.get_for_object(kwargs.pop('instances')[0])[0].field_dict
except IndexError:
for field in fieldList:
commentDict[field] = "Created"
except TypeError:
for field in fieldList:
commentDict[field] = "Deleted"
else:
for field in fieldList:
try:
pastTest = pastVersion[field]
except KeyError:
commentDict[field] = "Created"
else:
if currentVersion[field] != pastTest:
commentDict[field] = "Changed"
else:
commentDict[field] = "Unchanged"
comment = commentDict
revision = kwargs.pop('revision')
revision.comment = comment
revision.save()
kwargs['revision'] = revision
sender.save_revision
2/3) Для этого вам необходимо использовать систему разрешений на уровне объектов. Я реализовал Джанго-хранитель. Практически единственным ограничением сложности, которое вы можете реализовать, является количество вещей, которые вы можете выполнять самостоятельно. Базовый набор разрешений, которые вам нужно реализовать, - это просмотр, редактирование, удаление и некоторая роль контроллера / менеджера данных; однако, вы, вероятно, захотите пойти сложнее. Я бы настоятельно рекомендовал использовать представления на основе классов и миксины для проверки разрешений, но функция на основе может также работать. Это также может быть использовано для запроса пароля для определенных действий, потому что вы можете контролировать то, что происходит с полем, как вам нравится.
https://github.com/lukaszb/django-guardian
4) Истекающие пароли могут быть реализованы даже с помощью только системы аутентификации Django или любого приложения для управления учетными записями пользователей. Вам просто нужно будет добавить дополнительное поле, чтобы записать дату и время начала отсчета. Затем при входе в систему просто проверьте время обратного отсчета и посмотрите, не вышли ли они за пределы окна, и, если это так, потребуйте, чтобы они создали новый пароль, направив их через встроенное представление для изменения пароля или какой механизм подходит вашему приложению.
Я скажу вам, что наиболее трудной частью реализации CFR 21 Part 11 будет поиск соответствующих людей, которые точно скажут вам, что должен делать ваш проект для удовлетворения требований, а проверка на соответствие может потребовать много времени и затрат.
Надеюсь, это поможет вам начать.
Django Reversion может дать вам старт на контрольном курсе, хотя вам, вероятно, не нужны все его возможности.
Для 2, 3 и 4 в вашем списке, это вещи, которые вы, скорее всего, в конечном итоге закодировать самостоятельно.