text: from datetime import datetime
  
  from pulsar.api import PermissionDenied, Http404
  
  from lux.core import http_assert
  from lux.ext.rest import RestRouter, route
  from lux.models import Schema, fields, ValidationError
  from lux.ext.odm import Model
  
  from . import ensure_service_user, IdSchema
  
  
  URI = 'registrations'
  
  
  email_templates = {
      "subject": {
          1: "registration/activation_email_subject.txt",
          2: "registration/password_email_subject.txt"
      },
      "message": {
          1: "registration/activation_email.txt",
          2: "registration/password_email.txt"
      }
  }
  
  
  class RegistrationSchema(Schema):
      user = fields.Nested('UserSchema')
  
      class Meta:
          model = URI
  
  
  class PasswordSchema(Schema):
      """Schema for checking a password is input correctly
      """
      password = fields.Password(required=True, minLength=5, maxLength=128)
      password_repeat = fields.Password(required=True)
  
      def post_load(self, data):
          password = data['password']
          password_repeat = data.pop('password_repeat', None)
          if password != password_repeat:
              raise ValidationError('Passwords did not match')
  
  
  class UserCreateSchema(PasswordSchema):
      username = fields.Slug(required=True, minLength=2, maxLength=30)
      email = fields.Email(required=True)
  
  
  class RegistrationModel(Model):
  
      @property
      def type(self):
          return self.metadata.get('type', 1)
  
      def create_instance(self, session, data):
          data['active'] = False
          user = self.app.auth.create_user(session, **data)
          # send_email_confirmation(request, reg)
          return user
  
      def update_model(self, request, instance, data, session=None, **kw):
          if not instance.id:
              return super().update_model(request, instance, data,
                                          session=session, **kw)
          reg = self.instance(instance).obj
          http_assert(reg.type == self.type, Http404)
          self.update_registration(request, reg, data, session=session)
          return {'success': True}
  
      def update_registration(self, request, reg, data, session=None):
          with self.session(request, session=session) as session:
              user = reg.user
              user.active = True
              session.add(user)
              session.delete(reg)
  
  
  class RegistrationCRUD(RestRouter):
      """
      ---
      summary: Registration to the API
      tags:
          - authentication
          - registration
      """
      model = RegistrationModel("registrations", RegistrationSchema)
  
      @route(default_response_schema=[RegistrationSchema])
      def get(self, request):
          """
          ---
          summary: List registration objects
          responses:
              200:
                  description: List of registrations matching filters
          """
          return self.model.get_list_response(request)
  
      @route(default_response=201,
             default_response_schema=RegistrationSchema,
             body_schema=UserCreateSchema)
      def post(self, request, **kw):
          """
          ---
          summary: Create a new registration
          """
          ensure_service_user(request)
          return self.model.create_response(request, **kw)
  
      @route('<id>/activate', path_schema=IdSchema)
      def post_activate(self, request):
          """
          ---
          summary: Activate a user from a registration ID
          description: Clients should POST to this endpoint once they are
              happy the user has confirm his/her identity.
              This is a one time only operation.
          responses:
              204:
                  description: Activation was successful
              400:
                  description: Bad Token
              401:
                  description: Token missing or expired
              404:
                  description: Activation id not found
          """
          ensure_service_user(request)
          model = self.get_model(request)
  
          with model.session(request) as session:
              reg = self.get_instance(request, session=session)
              if reg.expiry < datetime.utcnow():
                  raise PermissionDenied('registration token expired')
                  reg.user.active = True
              session.add(reg.user)
              model.delete_model(request, reg, session=session)
  
          request.response.status_code = 204
          return request.response
  
  
  def send_email_confirmation(request, reg, email_subject=None,
                              email_message=None):
      """Send an email to user
      """
      user = reg.user
      if not user.email:
          return
      app = request.app
      token = ensure_service_user(request)
      site = token.get('url')
      reg_url = token.get('registration_url')
      psw_url = token.get('password_reset_url')
      ctx = {'auth_key': reg.id,
             'register_url': reg_url,
             'reset_password_url': psw_url,
             'expiration': reg.expiry,
             'email': user.email,
             'site_uri': site}
  
      email_subject = email_subject or email_templates['subject'][reg.type]
      email_message = email_message or email_templates['message'][reg.type]
  
      subject = app.render_template(email_subject, ctx)
      # Email subject *must not* contain newlines
      subject = ''.join(subject.splitlines())
      body = app.render_template(email_message, ctx)
      user.email_user(app, subject, body)
  