allow account validation through API (#33472)

- validation_context is limited to online and office.
- un-validation is forbidden.
- validating an already validated account is also forbidden.
- validation is only possible for OIDC clients
- on validation the OIDC client's OU slug is copied to the
  validation_partner attribute
This commit is contained in:
Benjamin Dauvergne 2019-06-04 22:34:06 +02:00
parent a2ee176a2f
commit a94cfe7847
1 changed files with 55 additions and 2 deletions

View File

@ -16,6 +16,8 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import logging
import django.apps
from django.conf import settings
@ -26,6 +28,7 @@ from django.core.urlresolvers import reverse_lazy
from authentic2.constants import AUTHENTICATION_EVENTS_SESSION_KEY
logger = logging.getLogger(__name__)
class AppConfig(django.apps.AppConfig):
name = 'authentic2_cut'
@ -277,8 +280,12 @@ class AppConfig(django.apps.AppConfig):
serializer.fields['family_name'] = serializers.CharField(read_only=True,
source='last_name')
serializer.fields['email_verified'].read_only = True
serializer.fields['validation_context'].read_only = True
serializer.fields['validation_date'].read_only = True
serializer.fields['validation_context'] = serializers.ChoiceField(
source='attributes.validation_context',
choices=[
('online', 'online'),
('office', 'office'),
])
serializer.fields['creation_mode'].read_only = True
serializer.fields['creation_partner'].read_only = True
serializer.fields['creation_domain'].read_only = True
@ -312,6 +319,52 @@ class AppConfig(django.apps.AppConfig):
return instance
serializer.create = new_create
old_update = serializer.update
def new_update(instance, validated_data):
validated = validated_data.get('attributes', {}).get('validated')
instance = old_update(instance, validated_data)
if validated:
logging.info('validated')
request = serializer.context['request']
if hasattr(request.user, 'oidc_client'):
partner = request.user.oidc_client.slug
else:
raise NotImplementedError
instance.attributes.validation_partner = partner
return instance
serializer.update = new_update
validation_variables = ['validated', 'validation_context', 'validation_date']
old_validate = serializer.validate
def new_validate(data):
data = old_validate(data)
attributes = data.get('attributes', {})
instance = serializer.instance
if instance:
if set(attributes) & set(validation_variables):
if instance.attributes.validated:
raise serializers.ValidationError(
'account already validated you cannot modify the validation status')
if not set(validation_variables).issubset(set(attributes)):
raise serializers.ValidationError(
'validated, validation_context and validation_date are required together')
if attributes['validated'] is not True:
raise serializers.ValidationError(
'validated can only be true')
request = serializer.context['request']
if hasattr(request.user, 'oidc_client'):
pass
else:
raise serializers.ValidationError('you are not a partner, you cannot validate')
else:
if set(attributes) & set(validation_variables):
raise serializers.ValidationError('you cannot validate during creation')
return data
serializer.validate = new_validate
# execute after other modifiers
a2_hook_api_modify_serializer.order = 999