Esempio n. 1
0
class EmergencyContact(models.Model):
    user = models.OneToOneField(User, blank=False)
    name = models.CharField(max_length=254, blank=True)
    relationship = models.CharField(max_length=254, blank=True)
    phone = PhoneNumberField(blank=True, null=True)
    email = models.EmailField(blank=True, null=True)
    last_updated = models.DateTimeField(auto_now_add=True)
Esempio n. 2
0
class UserProfile(models.Model):
    user = models.ForeignKey(User, unique=True)
    invitation_code = models.CharField(max_length=20)
    max_num_domains = models.IntegerField(default=8)
    contract_term_years = models.IntegerField(default=1, choices=TERM_CHOICES)
    pin = models.CharField(max_length=4, blank=True, default="")
    mobile_phone_number = PhoneNumberField(max_length=15, blank=True)
    organization_name = models.CharField(max_length=256)
    country = models.CharField(max_length=2, default="US")
    state = models.CharField(
        blank=True,
        max_length=2,
        choices=US_STATES,
    )
    city = models.CharField(max_length=256)
    preferred_language = models.CharField(max_length=2,
                                          blank=True,
                                          default="en")
    npi = models.CharField(max_length=20, default="", blank=True)
    email_verified = models.BooleanField(default=False)
    sms_verified = models.BooleanField(default=False)
    partner_code = models.CharField(max_length=20, default="", blank=True)
    creation_date = models.DateField(auto_now_add=True)
    renewal_date = models.DateField(auto_now_add=True)

    def __unicode__(self):
        return '%s, %s (%s)' % (self.user.last_name, self.user.first_name,
                                self.user.username)
Esempio n. 3
0
class Phone(models.Model):
    person = models.ForeignKey(Person)
    start_date = models.DateField('service start date', help_text=
            'Enter date this phone number went into service for this person \
                    with this carrier. Leave blank if that date cannot be determined.', 
                    blank=True, null=True, default=None)
    end_date = models.DateField('service end date', help_text=
            'Enter date this phone number for this person ended with this carrier. \
                    Leave blank if that date cannot be determined.', 
                    blank=True, null=True, default=None)
    valid_date = models.DateField(help_text='Enter a date when this phone \
            number was a valid way to contact this person.')
    invalid_date = models.DateField(help_text'Enter a date when this phone \
            number was no longer a valid way to contact this person.')
    phone_number = PhoneNumberField()
    carrier = models.CharField('carrier and type', help_text=
            "Enter phone-service provider's name and/or type \
                    (contract/prepaid/landline/voip/virtual). \
                    Leave blank if both provider and type cannot be determined.", 
                    blank=True, max_length=64)
    private = models.BooleanField(help_text='If marked as private, this phone \
            number will not be visible to other users of the database unless \
            given on a form like a rental applicaton. Anyone owning rental \
            units may gain access to any rental application in the database.')
    belongs = models.NullBooleanField('belongs to this person', help_text=
            'Does/did this phone number belong to this person? Should be \
                    checked if a service start date was entered.')

    def clean(self):
        if bool(start_date) and not belongs==True:
            raise ValidationError("Since there's a date for this phone number \
                    going into service for this person, you must check off the \
                    box showing this phone number does/did belong to this person. \
                    If this phone number never really belonged to this person, \
                    delete the service start date.")
Esempio n. 4
0
class Customer(User):
	#inheriting all fields from auth.User too
	street1 = models.CharField(max_length=60, verbose_name="Address	1")
	street2 = models.CharField(max_length=60, blank=True, verbose_name="Address	2")
	city = models.CharField(max_length=30)
	state = USPostalCodeField(blank=True)
	zip_code = models.CharField(max_length=10, verbose_name="Zip Code")
	phone = PhoneNumberField()
	owner = models.ForeignKey('self', null=True)
Esempio n. 5
0
class Call(models.Model):
    phone_number = PhoneNumberField(blank=False)
    caller_id_name = models.CharField(max_length=30, blank=False)
    rang_at = models.DateTimeField()
    customer = models.ForeignKey(Customer)

    def __str__(self):
        callid = "{} from {} {}".format(self.rang_at, self.phone_number,
                                        self.caller_id_name)
        return callid
Esempio n. 6
0
class EmergencyContact(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL, blank=False, on_delete=models.CASCADE)
    name = models.CharField(max_length=254, blank=True)
    relationship = models.CharField(max_length=254, blank=True)
    phone = PhoneNumberField(blank=True, null=True)
    email = models.EmailField(blank=True, null=True)
    last_updated = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return '%s - %s' % (self.user.username, self.name)
Esempio n. 7
0
class Customer(models.Model):
    first_name = models.CharField(max_length=15, default="")
    last_name = models.CharField(max_length=15, blank=False, default="")
    home_phone = PhoneNumberField(blank=False, unique=True)
    work_phone = PhoneNumberField(blank=True)
    email = models.EmailField(blank=True)
    veterinarian = models.CharField(max_length=30, blank=True)
    notes = models.TextField(blank=True)

    class Meta:
        ordering = ['last_name', 'first_name']

    def _get_full_name(self):
        "Returns the person's full name."
        return '%s %s' % (self.first_name, self.last_name)

    name = property(_get_full_name)

    def __str__(self):
        return '%s %s' % (self.first_name, self.last_name)

    def get_absolute_url(self):
        return reverse('customer_detail', kwargs={'pk': self.pk})
Esempio n. 8
0
class UserProfile(models.Model):
    MAX_PHOTO_SIZE = 1024

    user = models.OneToOneField(settings.AUTH_USER_MODEL, blank=False, related_name="profile", on_delete=models.CASCADE)
    phone = PhoneNumberField(blank=True, null=True)
    phone2 = PhoneNumberField("Alternate Phone", blank=True, null=True)
    address1 = models.CharField(max_length=128, blank=True)
    address2 = models.CharField(max_length=128, blank=True)
    city = models.CharField(max_length=128, blank=True)
    state = models.CharField(max_length=2, blank=True)
    zipcode = models.CharField(max_length=16, blank=True)
    bio = models.TextField(blank=True, null=True)
    public_profile = models.BooleanField(default=False)
    gender = models.CharField(max_length=1, choices=GENDER_CHOICES, default="U")
    pronouns = models.CharField(max_length=64, blank=True, null=True)
    howHeard = models.ForeignKey(HowHeard, blank=True, null=True, on_delete=models.CASCADE)
    #referred_by = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name="Referred By", related_name="referral", blank=True, null=True, on_delete=models.CASCADE)
    industry = models.ForeignKey(Industry, blank=True, null=True, on_delete=models.CASCADE)
    neighborhood = models.ForeignKey(Neighborhood, blank=True, null=True, on_delete=models.CASCADE)
    has_kids = models.NullBooleanField(blank=True, null=True)
    self_employed = models.NullBooleanField(blank=True, null=True)
    last_modified = models.DateField(auto_now=True, editable=False)
    photo = models.ImageField(upload_to=user_photo_path, blank=True, null=True)
    tags = TaggableManager(blank=True)
    valid_billing = models.NullBooleanField(blank=True, null=True)
    websites = models.ManyToManyField(Website, blank=True)

    @property
    def url_personal(self):
        return self.websites.filter(url_type__name="personal").first()

    @property
    def url_professional(self):
        return self.websites.filter(url_type__name="professional").first()

    @property
    def url_facebook(self):
        return self.websites.filter(url_type__name="facebook").first()

    @property
    def url_twitter(self):
        return self.websites.filter(url_type__name="twitter").first()

    @property
    def url_linkedin(self):
        return self.websites.filter(url_type__name="linkedin").first()

    @property
    def url_github(self):
        return self.websites.filter(url_type__name="github").first()

    def save_url(self, url_type, url_value):
        if url_type and url_value:
            w = self.websites.filter(url_type__name=url_type).first()
            if w:
                w.url = url_value
                w.save()
            else:
                t = URLType.objects.get(name=url_type)
                self.websites.create(url_type=t, url=url_value)

    def active_organization_memberships(self, target_date=None):
        if not target_date:
            target_date = localtime(now()).date()
        future = Q(end_date__isnull=True)
        unending = Q(end_date__gte=target_date)
        return self.user.organizationmember_set.filter(start_date__lte=target_date).filter(future | unending)

    def past_organization_memberships(self, target_date=None):
        if not target_date:
            target_date = localtime(now()).date()
        return self.user.organizationmember_set.filter(end_date__lte=target_date)

    def active_organizations(self, target_date=None):
        active = self.active_organization_memberships(target_date)
        return Organization.objects.filter(id__in=active.values('organization'))

    def outstanding_bills(self):
        """Returns all outstanding bills for this user """
        from nadine.models.billing import UserBill
        return UserBill.objects.outstanding().filter(user=self.user)

    @property
    def outstanding_amount(self):
        """Returns total of all open bills for this user """
        total = 0
        for b in self.outstanding_bills():
            total += b.total_owed
        return total

    def open_xero_invoices(self):
        from nadine.utils.xero_api import XeroAPI
        xero_api = XeroAPI()
        return xero_api.get_open_invoices(self.user)

    def pay_bills_form(self):
        from nadine.forms import PaymentForm
        return PaymentForm(initial={'username': self.user.username, 'amount': self.open_bills_amount})

    def days_used(self, target_date=None):
        membership = Membership.objects.for_user(self.user, target_date)
        days = membership.coworking_days_in_period(target_date)
        billable = days.filter(payment="Bill")
        allowed = membership.coworking_day_allowance(target_date)
        return (days.count(), allowed, billable.count())

    def all_emails(self):
        # Done in two queries so that the primary email address is always on top.
        primary = self.user.emailaddress_set.filter(is_primary=True)
        non_primary = self.user.emailaddress_set.filter(is_primary=False)
        return list(primary) + list(non_primary)

    def non_primary_emails(self):
        return self.user.emailaddress_set.filter(is_primary=False)

    def duration(self):
        return relativedelta(localtime(now()).date(), self.first_visit)

    def duration_str(self, include_days=False):
        retval = ""
        delta = self.duration()
        if delta.years:
            if delta.years == 1:
                retval = "1 year"
            else:
                retval = "%d years" % delta.years
            if delta.months or delta.days:
                retval += " and "
        if delta.months:
            if delta.months == 1:
                retval += "1 month"
            else:
                retval += "%d months" % delta.months
            if include_days and delta.days:
                retval += " and "
        if include_days and delta.days:
            if delta.days == 1:
                retval += "1 day"
            else:
                retval += "%d days" % delta.days
        return retval

    def hosted_days(self):
        return CoworkingDay.objects.filter(paid_by=self.user).order_by('-visit_date')

    def has_file_uploads(self):
        return FileUpload.objects.filter(user=self.user).count() > 0

    def has_file(self, doc_type):
        return FileUpload.objects.filter(user=self.user, document_type=doc_type).count() > 0

    def file_uploads(self):
        files = {}
        # Only want the latest one if there are duplicates
        for f in FileUpload.objects.filter(user=self.user).order_by('uploadTS').reverse():
            files[f.name] = f
        return list(files.values())

    def files_by_type(self):
        files = {}
        # Only want the latest one if there are duplicates
        for f in FileUpload.objects.filter(user=self.user).order_by('uploadTS').reverse():
            files[f.document_type] = f
        return files

    def alerts_by_key(self, include_resolved=False):
        from nadine.models.alerts import MemberAlert
        if include_resolved:
            alerts = MemberAlert.objects.filter(user=self.user)
        else:
            alerts = MemberAlert.objects.filter(user=self.user, resolved_ts__isnull=True, muted_ts__isnull=True)
        alerts_by_key = {}
        for alert in alerts:
            if alert.key in alerts_by_key:
                alerts_by_key[alert.key].append(alert)
            else:
                alerts_by_key[alert.key] = [alert]
        return alerts_by_key

    def alerts(self):
        from nadine.models.alerts import MemberAlert
        return MemberAlert.objects.filter(user=self.user).order_by('-created_ts')

    def open_alerts(self):
        from nadine.models.alerts import MemberAlert
        return MemberAlert.objects.filter(user=self.user, resolved_ts__isnull=True, muted_ts__isnull=True).order_by('-created_ts')

    def resolve_alerts(self, alert_key, resolved_by=None):
        logger.debug("resolve_alerts: user=%s, key=%s, resolved_by=%s" % (self.user, alert_key, resolved_by))
        from nadine.models.alerts import MemberAlert
        alerts = MemberAlert.objects.filter(user=self.user, key=alert_key, resolved_ts__isnull=True, muted_ts__isnull=True).order_by('-created_ts')
        if alerts:
            for alert in alerts:
                alert.resolve(resolved_by)

    @property
    def first_visit(self):
        first_visit = date.max
        first_day = CoworkingDay.objects.filter(user=self.user).order_by('visit_date').first()
        if first_day:
            if first_day.visit_date < first_visit:
                first_visit = first_day.visit_date
        individual_membership = IndividualMembership.objects.get(user=self.user)
        first_subscription = ResourceSubscription.objects.filter(membership=individual_membership).order_by('start_date').first()
        if first_subscription:
            if first_subscription.start_date < first_visit:
                first_visit = first_subscription.start_date
        # TODO - pull the first time we saw them in an organization
        if first_visit < date.max:
            return first_visit
        return None

    @property
    def last_visit(self):
        last_visit = date.min
        last_day = CoworkingDay.objects.filter(user=self.user).order_by('visit_date').last()
        if last_day:
            if last_day.visit_date > last_visit:
                last_visit = last_day.visit_date
        individual_membership = IndividualMembership.objects.get(user=self.user)
        last_subscription = ResourceSubscription.objects.filter(membership=individual_membership).order_by('start_date').last()
        if last_subscription and last_subscription.end_date:
            if last_subscription.end_date > last_visit:
                last_visit = last_subscription.end_date
        # TODO - pull the last time we saw them in an organization
        if last_visit > date.min:
            return last_visit
        return None

    @property
    def membership_type(self):
        membership_type = ""
        membership = Membership.objects.for_user(self.user)
        if membership:
            if not membership.is_active():
                membership_type += "Ex "
            if membership.is_organization:
                membership_type += "Org "

            # Evaluate our package name
            package_name = membership.package_name()
            if package_name:
                membership_type += package_name
                if not membership.package_is_pure():
                    membership_type += " *"
            if len(membership_type) > 0:
                return membership_type

        # Now check daily logs
        drop_ins = CoworkingDay.objects.filter(user=self.user).count()
        if drop_ins == 0:
            return "New User"
        elif drop_ins == 1:
            return "First Day"
        else:
            return "Drop-in"

    def active_subscriptions(self, target_date=None):
        return ResourceSubscription.objects.active_subscriptions_with_username(target_date).filter(username=self.user.username)

    def is_active(self, target_date=None):
        return self.active_subscriptions(target_date).count() > 0

    def is_guest(self, target_date=None):
        for s in self.active_subscriptions(target_date):
            if s.paid_by is not None:
                return True
        return False

    def hosts(self, target_date=None):
        hosts = []
        for s in self.active_subscriptions(target_date):
            if s.paid_by is not None and s.paid_by not in hosts:
                hosts.append(s.paid_by)
        return hosts

    def guests(self, target_date=None):
        guests = []
        for subscription in ResourceSubscription.objects.active_subscriptions_with_username(target_date).filter(paid_by=self.user):
            guest = User.objects.get(username=subscription.username)
            if guest not in guests:
                guests.append(guest)
        return guests

    def has_valid_billing(self, lookup_new_card=True):
        hosts = self.hosts()
        if hosts:
            for host in hosts:
                if not host.profile.has_valid_billing():
                    # If just one host has invalid billing...
                    return False
            # All hosts have valid billing
            return True

        if self.valid_billing is None and lookup_new_card:
            logger.debug("%s: Null Valid Billing.  Looking for new card..." % self)
            if self.has_new_card():
                logger.debug("%s: Found new card.  Marking billing valid." % self)
                self.valid_billing = True
                self.save()
            else:
                return False
        return self.valid_billing

    def has_billing_profile(self):
        try:
            api = PaymentAPI()
            if api.get_customers(self.user.username):
                return True
        except Exception:
            pass
        return False

    def has_new_card(self):
        # Check for a new card.  WARNING: kinda expensive
        try:
            api = PaymentAPI
            return api.has_new_card(self.user.username)
        except Exception:
            pass
        return False

    def auto_bill_enabled(self):
        if not hasattr(settings, 'USA_EPAY_SOAP_KEY'):
            return None
        api = PaymentAPI()
        return api.auto_bill_enabled(self.user.username)

    def membership_days(self):
        total_days = 0
        for membership in self.membership_history():
            end = membership.end_date
            if not end:
                end = localtime(now()).date()
            diff = end - membership.start_date
            days = diff.days
            total_days = total_days + days
        return total_days

    def average_bill(self):
        from nadine.models.billing import UserBill
        bills = UserBill.objects.filter(user=self.user)
        if bills:
            bill_totals = 0
            for b in bills:
                bill_totals = bill_totals + b.amount
            return bill_totals / len(bills)
        return 0

    def is_manager(self):
        if self.user.is_staff: return True
        managers = User.helper.managers(include_future=True)
        return self.user in managers

    def __str__(self): return '%s %s' % (smart_str(self.user.first_name), smart_str(self.user.last_name))

    def get_absolute_url(self):
        return reverse('member:profile:view', kwargs={'username': self.user.username})

    def get_staff_url(self):
        return reverse('staff:members:detail', kwargs={'username': self.user.username})

    class Meta:
        app_label = 'nadine'
        ordering = ['user__first_name', 'user__last_name']
        get_latest_by = "last_modified"
Esempio n. 9
0
class Player(models.Model):
    """Game-related data about a user"""

    TEAMS = {
        "H": "Humans",
        "Z": "Zombies",
    }

    UPGRADES = {
        'O': "Original Zombie",
        'P': "Pacifist",
        'n': "Noodler",
        'N': "Noodler II",
        'B': "Black Ops",
        'C': "Charger",
        "D": "Double Tap",
        "S": "Screamer",
        "E": "Bone Zombie",
    }

    user = models.ForeignKey(User)
    cell = PhoneNumberField(blank=True, null=True)

    game = models.ForeignKey(Game)

    school = models.ForeignKey(School, related_name="player_set")
    mailbox = models.CharField(max_length=20, null=True, blank=True)
    dorm = models.ForeignKey(Building)
    grad_year = models.PositiveIntegerField(blank=True, null=True)

    can_oz = models.BooleanField(default=False)

    feed = FeedCodeField()

    brains = models.IntegerField(default=0)

    notes = models.CharField(max_length=255, null=True, blank=True)

    team = models.CharField(
        max_length=1,
        choices=TEAMS.items(),
        default="H",
    )

    clan = models.CharField(
        max_length=32,
        null=True,
        blank=True,
    )

    upgrade = models.CharField(
        max_length=1,
        choices=UPGRADES.items(),
        blank=True,
        null=True,
    )


    def __unicode__(self):
        return u"Player: {}".format(self.user.get_full_name())

    @classmethod
    def current_players(cls):
        """Return all Players in the current Game."""
        return cls.objects.filter(game=Game.nearest_game())

    @classmethod
    def logged_in_player(cls, request):
        """Return the currently logged in Player."""
        return cls.current_players().get(user=request.user)

    @classmethod
    def user_to_player(cls, u, game=None):
        """Return the most current Player corresponding to the given User.

        Because a User has multiple players, you can specify which
        player to retrieve by passing a Game.

        """
        if u.is_anonymous():
            raise Player.DoesNotExist

        game = game or Game.nearest_game()
        return cls.objects.get(game=game, user=u)


    class Meta:
        # A User can only have one Player per Game, and a feed code
        # can only correspond to one player per game.
        unique_together = (('user', 'game'), ('feed', 'game'))
Esempio n. 10
0
class User(AbstractUser):
    email = models.EmailField(_('email address'), unique=True)

    uuid = models.UUIDField(unique=True, db_index=True, default=uuid4)
    title = models.CharField(max_length=255, null=True, blank=True)
    organizations = models.ManyToManyField('organizations.Organization')
    timezone = TimeZoneField(default=settings.TIME_ZONE, blank=True)
    access_new_projects = models.BooleanField(default=False)

    # Phone numbers
    fax = PhoneNumberField(null=True, blank=True)
    home = PhoneNumberField(null=True, blank=True)
    mobile = PhoneNumberField(null=True, blank=True)
    office = PhoneNumberField(null=True, blank=True)
    ext = models.CharField(max_length=10, null=True, blank=True)

    last_updated = models.DateTimeField(auto_now=True)
    removed = models.DateField(null=True)
    avatar_url = models.URLField(max_length=1200)

    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    class Meta:
        ordering = ['first_name', 'last_name']
        db_table = 'kala_user'

    def set_active(self, active):
        self.is_active = active
        if not self.is_active:
            self.removed = datetime.date.today()
        self.save()

    def get_organizations_with_create(self):
        if self.is_superuser:
            return organizations.models.Organization.objects.all()
        return organizations.models.Organization.objects.filter(
            uuid__in=Permissions.objects.filter(
                user=self, permission__codename='add_organization').
            values_list('object_uuid', flat=True))

    def get_organizations(self):
        if self.is_superuser:
            return organizations.models.Organization.objects.active()
        project_uuids = Permissions.objects.filter(
            user=self,
            permission__codename__in=[
                'change_project', 'add_project', 'delete_project'
            ]).values_list('object_uuid', flat=True)
        project_org_uuids = projects.models.Project.objects.filter(
            uuid__in=project_uuids).values_list('organization__uuid',
                                                flat=True)
        org_uuids = Permissions.objects.filter(user=self,
                                               permission__codename__in=[
                                                   'change_organization',
                                                   'add_organization',
                                                   'delete_organization'
                                               ]).values_list('object_uuid',
                                                              flat=True)
        document_project_uuids = Permissions.objects.filter(
            permission__codename__in=[
                'change_document', 'add_document', 'delete_document'
            ],
            user=self).values_list('object_uuid', flat=True)
        document_projects = documents.models.Document.objects.filter(
            uuid__in=document_project_uuids).values_list(
                'project__organization__uuid', flat=True)
        return organizations.models.Organization.objects.filter(
            uuid__in=list(project_org_uuids) + list(org_uuids) +
            list(document_projects))

    def get_projects(self):
        if self.is_superuser:
            return projects.models.Project.objects.active()
        else:
            return projects.models.Project.objects.active().filter(
                organization__id__in=self.get_organizations().values_list(
                    'pk', flat=True))

    def get_documents(self):
        if self.is_superuser:
            return documents.models.Document.objects.all()
        else:
            projects = self.get_organizations().values_list('project__uuid',
                                                            flat=True)
            document_uuids = documents.models.Document.objects.filter(
                project__uuid__in=projects).values_list('uuid', flat=True)

            perm_uuids = Permissions.objects.filter(
                user=self,
                object_uuid__in=document_uuids).values_list('object_uuid',
                                                            flat=True)

            return documents.models.Document.objects.filter(
                uuid__in=list(perm_uuids) +
                list(document_uuids)).prefetch_related(
                    'documentversion_set',
                    'documentversion_set__user',
                ).select_related('project')

    def get_users(self):
        if self.is_superuser:
            return User.objects.all()
        else:
            organizations = self.get_organizations().values_list('pk')
            return User.objects.filter(organizations__in=organizations)

    def send_invite(self):
        pass

    def add_perm(self, perm, uuid):
        Permissions.add_perm(perm=perm, user=self, uuid=uuid)

    def has_perm(self, perm, uuid):
        return Permissions.has_perm(perm=perm, user=self, uuid=uuid)

    def add_read(self, user):
        perm = Permission.objects.get(codename='change_user')
        Permissions.add_perm(perm=perm, user=user, uuid=self.uuid)

    def has_read(self, user):
        perm = Permission.objects.get(codename='change_user')
        return Permissions.has_perm(perm=perm, user=user, uuid=self.uuid)

    def add_delete(self, user):
        perm = Permission.objects.get(codename='delete_user')
        Permissions.add_perm(perm=perm, user=user, uuid=self.uuid)

    def has_delete(self, user):
        perm = Permission.objects.get(codename='delete_user')
        return Permissions.has_perm(perm=perm, user=user, uuid=self.uuid)

    def add_create(self, user):
        perm = Permission.objects.get(codename='add_user')
        Permissions.add_perm(perm=perm, user=user, uuid=self.uuid)

    def has_create(self, user):
        perm = Permission.objects.get(codename='add_user')
        return Permissions.has_perm(perm=perm, user=user, uuid=self.uuid)

    def __str__(self):  # pragma: no cover
        return "{0} {1}".format(self.first_name, self.last_name)
Esempio n. 11
0
class Organization(models.Model):
    name = models.CharField(max_length=255, unique=True)
    uuid = models.UUIDField(unique=True, db_index=True, default=uuid4)
    address = models.CharField(max_length=255, null=True, blank=True)
    address1 = models.CharField(max_length=255, null=True, blank=True)
    city = models.CharField(max_length=255, null=True, blank=True)
    state = models.CharField(max_length=80, null=True, blank=True)
    zip = models.CharField(max_length=25, null=True, blank=True)
    country = models.CharField(max_length=80,
                               null=True,
                               blank=True,
                               default='US')
    fax = PhoneNumberField(null=True, blank=True)
    phone = PhoneNumberField(null=True, blank=True)
    locale = models.CharField(max_length=2,
                              null=True,
                              blank=True,
                              default='en')
    removed = models.DateField(null=True)
    timezone = TimeZoneField(default=settings.TIME_ZONE)
    website = models.URLField(null=True, blank=True)

    is_active = models.BooleanField(default=True)

    objects = ActiveManager()
    with_projects = OrganizationsWithProjectManager()

    class Meta:
        ordering = ['name']
        db_table = 'kala_companies'

    def set_active(self, active):
        self.is_active = active
        for person in self.user_set.all():
            person.set_active(active)

        for project in Project.objects.filter(organization=self):
            project.set_active(active)

        if not self.is_active:
            self.removed = datetime.date.today()
        self.save()

    def get_projects(self, user):
        if user.is_superuser:
            return Project.objects.active().filter(organization=self)
        if Permissions.has_perms(
            ['change_organization', 'add_organization', 'delete_organization'],
                user, self.uuid):
            return self.project_set.all()
        else:
            document_project_uuids = Permissions.objects.filter(
                permission__codename__in=[
                    'change_document', 'add_document', 'delete_document'
                ],
                user=user).values_list('object_uuid', flat=True)
            document_projects = documents.models.Document.objects.filter(
                project__organization=self,
                uuid__in=document_project_uuids).values_list('project__uuid',
                                                             flat=True)

            project__uuids = self.project_set.all().values_list('uuid',
                                                                flat=True)
            perm_uuids = Permissions.objects.filter(
                user=user,
                object_uuid__in=project__uuids).values_list('object_uuid',
                                                            flat=True)
            return Project.objects.filter(uuid__in=list(perm_uuids) +
                                          list(document_projects))

    def get_people(self, user):
        # If you are a super user or you have permissions on
        # an organization, then you can see everyone.
        if user.is_superuser or Permissions.has_perms(
            ['change_organization', 'add_organization', 'delete_organization'],
                user, self.uuid):
            return User.objects.all()
        else:
            return None

    def __str__(self):
        return self.name

    def add_change(self, user):
        perm = Permission.objects.get(codename='change_organization')
        Permissions.add_perm(perm=perm, user=user, uuid=self.uuid)

    def has_change(self, user):
        perm = Permission.objects.get(codename='change_organization')
        return Permissions.has_perm(perm=perm, user=user, uuid=self.uuid)

    def add_delete(self, user):
        perm = Permission.objects.get(codename='delete_organization')
        Permissions.add_perm(perm=perm, user=user, uuid=self.uuid)

    def has_delete(self, user):
        perm = Permission.objects.get(codename='delete_organization')
        return Permissions.has_perm(perm=perm, user=user, uuid=self.uuid)

    def add_create(self, user):
        perm = Permission.objects.get(codename='add_organization')
        Permissions.add_perm(perm=perm, user=user, uuid=self.uuid)

    def has_create(self, user):
        perm = Permission.objects.get(codename='add_organization')
        return Permissions.has_perm(perm=perm, user=user, uuid=self.uuid)
Esempio n. 12
0
class User(AbstractUser):
    email = models.EmailField(_('email address'), unique=True)

    uuid = models.UUIDField(unique=True, db_index=True, default=uuid4)
    title = models.CharField(max_length=255, null=True, blank=True)
    organizations = models.ManyToManyField('organizations.Organization')
    timezone = TimeZoneField(default=settings.TIME_ZONE, blank=True)
    access_new_projects = models.BooleanField(default=False)

    # Phone numbers
    fax = PhoneNumberField(null=True, blank=True)
    home = PhoneNumberField(null=True, blank=True)
    mobile = PhoneNumberField(null=True, blank=True)
    office = PhoneNumberField(null=True, blank=True)
    ext = models.CharField(max_length=10, null=True, blank=True)

    last_updated = models.DateTimeField(auto_now=True)
    removed = models.DateField(null=True)
    avatar_url = models.URLField(max_length=1200)

    objects = KalaUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    class Meta:
        ordering = ['first_name', 'last_name']
        db_table = 'kala_user'

    def set_active(self, active):
        self.is_active = active
        if not self.is_active:
            self.removed = datetime.date.today()
        self.save()

    def get_organizations_with_create(self):
        if self.is_superuser:
            return organizations.models.Organization.objects.active()
        return organizations.models.Organization.objects.active().filter(
            id__in=organizations.models.OrganizationPermission.objects.filter(
                user=self).values_list('organization__id', flat=True))

    def get_organizations(self, permission=None):
        if self.is_superuser:
            return organizations.models.Organization.objects.active()
        else:
            kwargs = {'user': self}
            if permission:
                kwargs['permission__codename__in'] = permission

            return organizations.models.Organization.objects.active(
            ).filter(id__in=set().union(*[
                list(
                    organizations.models.OrganizationPermission.objects.filter(
                        **kwargs).values_list('organization__id', flat=True)),
                list(
                    projects.models.ProjectPermission.objects.filter(
                        **kwargs).values_list('project__organization__id',
                                              flat=True).values_list(
                                                  'id', flat=True)),
                list(
                    documents.models.DocumentPermission.objects.filter(
                        **kwargs).values_list(
                            'document__project__organization__id', flat=True))
            ]))

    def get_projects(self, permission=None):
        if self.is_superuser:
            return projects.models.Project.objects.active()
        else:
            kwargs = {'user': self}
            if permission:
                kwargs['permission__codename__in'] = permission
            return projects.models.Project.objects.active().filter(
                id__in=set().union(*[
                    list(
                        projects.models.ProjectPermission.objects.filter(
                            **kwargs).values_list('project__id', flat=True)),
                    list(
                        projects.models.Project.objects.filter(
                            organization__id__in=organizations.models.
                            OrganizationPermission.objects.filter(
                                **kwargs).values_list('organization__id',
                                                      flat=True)).values_list(
                                                          'id', flat=True)),
                    list(
                        documents.models.DocumentPermission.objects.filter(
                            **kwargs).values_list('document__project__id',
                                                  flat=True))
                ]))

    def get_documents(self):
        if self.is_superuser:
            return documents.models.Document.objects.active()
        else:
            return documents.models.Document.objects.active().filter(
                id__in=set().union(*[
                    list(
                        documents.models.DocumentPermission.objects.filter(
                            user=self).values_list('document__id', flat=True)),
                    list(
                        documents.models.Document.objects.filter(
                            project__id__in=projects.models.ProjectPermission.
                            objects.filter(user=self).values_list(
                                'project__id', flat=True)).values_list(
                                    'id', flat=True)),
                    list(
                        documents.models.Document.objects.filter(
                            project__organization__id__in=organizations.models.
                            OrganizationPermission.objects.filter(
                                user=self).values_list('organization__id',
                                                       flat=True)).values_list(
                                                           'id', flat=True))
                ]))

    def get_users(self):
        if self.is_superuser:
            return User.objects.all()
        else:
            organization_ids = self.get_organizations().values_list('id')
            return User.objects.filter(pk__in=set().union(*[
                list(
                    organizations.models.OrganizationPermission.objects.filter(
                        organization__id__in=organization_ids).values_list(
                            'user__id', flat=True)),
                list(
                    projects.models.ProjectPermission.objects.filter(
                        project__organization__id__in=organization_ids).
                    values_list('user_id', flat=True)),
                list(
                    documents.models.DocumentPermission.objects.filter(
                        document__project__organization__id__in=organization_ids
                    ).values_list('user_id', flat=True))
            ]))

    def send_invite(self, app, template, subject, object):
        template_txt = '{0}/{1}.txt'.format(app, template)
        if settings.USE_HTML_EMAIL:
            template_html = loader.get_template('{0}/{1}.html'.format(
                app, template))
        context = {
            'object': object,
            'user': self,
            'uid': urlsafe_base64_encode(force_bytes(self.pk)).decode(),
            'token': default_token_generator.make_token(self),
            'application_url': settings.APPLICATION_URL,
            'help_email': settings.HELP_EMAIL,
        }
        send_mail(
            subject,
            render_to_string(template_txt, context),
            settings.FROM_EMAIL,
            [self.email],
            fail_silently=False,
            #html_message=render(None, template_html, context) if settings.USE_HTML_EMAIL else None
        )

    def __str__(self):  # pragma: no cover
        return "{0} {1}".format(self.first_name, self.last_name)
Esempio n. 13
0
class DomainBoundCertificate(models.Model):
    trust_anchor = models.ForeignKey(TrustAnchorCertificate)
    status = models.CharField(max_length=10,
                              default="incomplete",
                              choices=STATUS_CHOICES)
    sha256_digest = models.CharField(
        max_length=64,
        default="",
        blank=True,
    )
    sha1_fingerprint = models.CharField(
        max_length=64,
        default="",
        blank=True,
    )
    #editable=False)
    serial_number = models.CharField(
        max_length=64,
        default=-01,
        blank=True,
    )
    #editable=False)
    domain = models.CharField(max_length=512,
                              default="",
                              help_text="This value should match the email.")
    common_name = models.CharField(max_length=512, default="")
    dns = models.CharField(
        max_length=512,
        default="",
        verbose_name="DNS",
        help_text="""This should always match the email field,
                                         unless you are creating a "bad"
                                         certificate for testing.
                                      """)
    email = models.CharField(max_length=512,
                             default="",
                             verbose_name="Email or Domain",
                             help_text="""For email-bound certificate use an
                            email address (e.g. [email protected])
                            For a domain-bound certificate use a domain (e.g.
                            "direct.example.com).""")
    rsa_keysize = models.IntegerField(max_length=4,
                                      default=2048,
                                      choices=RSA_KEYSIZE_CHOICES)
    country = models.CharField(max_length=2, default="US")
    state = models.CharField(blank=True, max_length=2, choices=US_STATES)
    city = models.CharField(
        max_length=64,
        help_text="Letters, numbers, and dashes okay. No slashes")
    organization = models.CharField(
        max_length=64,
        help_text="Letters, numbers, and dashes okay. No slashes")
    completed_dir_path = models.CharField(max_length=1024,
                                          default="",
                                          blank=True)
    public_key_path = models.CharField(max_length=1024, default="", blank=True)

    private_expire_days = models.IntegerField(max_length=2,
                                              default="1",
                                              blank=True)

    private_zip_name = models.CharField(max_length=512, default="", blank=True)

    presigned_zip_url = models.CharField(max_length=512,
                                         default="",
                                         blank=True)
    presigned_zip_s3 = models.CharField(max_length=512, default="", blank=True)

    public_cert_der_url = models.CharField(max_length=1024,
                                           default="",
                                           blank=True)
    public_cert_der_s3 = models.CharField(max_length=1024,
                                          default="",
                                          blank=True)

    public_cert_pem_url = models.CharField(max_length=1024,
                                           default="",
                                           blank=True)
    public_cert_pem_s3 = models.CharField(max_length=1024,
                                          default="",
                                          blank=True)

    public_cert_der_url = models.CharField(max_length=1024,
                                           default="",
                                           blank=True)
    public_cert_der_s3 = models.CharField(max_length=1024,
                                          default="",
                                          blank=True)

    public_cert_status_url = models.CharField(max_length=1024,
                                              default="",
                                              blank=True)

    public_cert_status_sha1_url = models.CharField(max_length=1024,
                                                   default="",
                                                   blank=True)

    public_cert_x5c_url = models.CharField(max_length=1024,
                                           default="",
                                           blank=True)

    revoke = models.BooleanField()
    revoked_note = models.TextField(max_length=512, blank=True, default="")
    verified = models.BooleanField()
    verified_message_sent = models.BooleanField()
    rcsp_response = models.TextField(max_length=512, blank=True, default="")
    notes = models.TextField(max_length=1024, blank=True, default="")
    npi = models.CharField(max_length=20, default="", blank=True)
    contact_first_name = models.CharField(max_length=100,
                                          default="",
                                          blank=True)
    contact_last_name = models.CharField(max_length=100,
                                         default="",
                                         blank=True)
    contact_email = models.EmailField()
    contact_mobile_phone = PhoneNumberField(max_length=15, blank=True)
    contact_land_phone = PhoneNumberField(max_length=15, blank=True)
    contact_fax = PhoneNumberField(max_length=15, blank=True)
    expiration_date = models.DateField(blank=True, editable=False)
    expire_days = models.IntegerField(max_length=5,
                                      default=365,
                                      choices=EXPIRE_CHOICES)
    creation_date = models.DateField(auto_now_add=True)

    def __unicode__(self):
        return '%s (%s) Status=%s, Created %s, Issued by %s' % (
            self.domain, self.serial_number, self.status, self.creation_date,
            self.trust_anchor.organization)

    class Meta:
        get_latest_by = "creation_date"
        ordering = ('-creation_date', )

    def save(self, **kwargs):
        if not self.sha256_digest and self.status == "incomplete":
            print "We've only just begun...I'm new."

            today = datetime.date.today()
            self.expiration_date = today + datetime.timedelta(
                days=self.expire_days)

            result = create_endpoint_certificate(
                common_name=self.common_name,
                email=self.email,
                dns=self.dns,
                anchor_dns=self.trust_anchor.dns,
                expires=self.expire_days,
                organization=self.organization,
                city=self.city,
                state=self.state,
                country=self.country,
                rsakey=self.rsa_keysize,
                user=self.trust_anchor.owner.username,
                public_key_path=self.trust_anchor.public_key_path,
                private_key_path=self.trust_anchor.private_key_path,
                completed_anchor_dir=self.trust_anchor.completed_dir_path)

            sha256_digest = result['sha256_digest']
            self.serial_number = result['serial_number']
            self.sha1_fingerprint = result['sha1_fingerprint']
            self.notes = result['notes']
            self.private_zip_name = result['anchor_zip_download_file_name']
            self.status = result['status']
            self.completed_dir_path = result['completed_dir_path']
            self.public_key_path = result['public_key_path']

            #send the verifier an email notification
            msg = """
            <html>
            <head>
            </head>
            <body>
            A new Direct Domain Bound certificate was created by %s and requires your review.
            Here is a link:
            <ul>
            <li><a href="https://console.directca.org/admin/certificates/domainboundcertificate/%s">%s</a></li>
            </ul>
            </body>
            </html>
            """ % (
                self.organization,
                self.id,
                self.domain,
            )
            if settings.SEND_CA_EMAIL:
                msg = EmailMessage(
                    '[DirectCA]A new Domain-Bound Certificate requires verification',
                    msg, settings.EMAIL_HOST_USER, [
                        settings.CA_VERIFIER_EMAIL,
                    ])
                msg.content_subtype = "html"  # Main content is now text/html
                msg.send()

            super(DomainBoundCertificate, self).save(**kwargs)
            return

        if self.verified and not self.verified_message_sent and \
           self.status in  ('unverified', 'good'):
            print "VERIFY ----------------------------"
            """ Mark the certificate as verified"""
            self.verified = True

            self.status = "good"
            # RCSP ------------------------------------------------------------
            rcsp_result = write_verification_message(
                self.serial_number,
                self.common_name,
                "good",
                self.sha1_fingerprint,
            )
            #Write it to db
            self.rcsp_response = rcsp_result

            #set the filename
            fn = "%s.json" % (self.serial_number)
            #Write it to file
            fp = os.path.join(self.completed_dir_path, fn)

            f = open(fp, "w")
            f.write(str(rcsp_result))
            f.close()

            #Upload the RCSP file to S3
            s = SimpleS3()
            if settings.USE_S3:
                self.public_cert_status_url = s.store_in_s3(
                    fn, fp, bucket=settings.RCSP_BUCKET, public=True)

                self.public_cert_status_url = s.build_pretty_url(
                    self.public_cert_status_url, settings.RCSP_BUCKET)

            #JOSE -------------------------------------------------------------
            #get all the files
            certfilelist = [
                settings.CA_PUBLIC_CERT, self.trust_anchor.public_key_path,
                self.public_key_path
            ]

            fn = "%s-chain.pem" % (self.dns)
            chained_cert_path = os.path.join(self.completed_dir_path, fn)
            certlist = chain_keys_in_list(chained_cert_path, certfilelist)
            #write the json

            x5c_json = write_x5c_message(self.email, certlist)

            # set the filename ------------------------------------------------
            fn = "%s-x5c.json" % (self.serial_number)

            # Write it to file ------------------------------------------------
            fp = os.path.join(self.completed_dir_path, fn)

            f = open(fp, "w")
            f.write(str(x5c_json))
            f.close()

            #Upload the x5c file to S3
            s = SimpleS3()
            if settings.USE_S3:
                key = "x5c/" + fn
                self.public_cert_x5c_url = s.store_in_s3(
                    key, fp, bucket=settings.X5C_BUCKET, public=True)
                self.public_cert_x5c_url = s.build_pretty_url(
                    self.public_cert_x5c_url, settings.X5C_BUCKET)

            #Calculate the SHA1 fingerprint & write it to a file
            digestsha1 = json.dumps(sha.sha1_from_filepath(fp), indent=4)
            fn = "%s-sha1.json" % (self.serial_number)
            fp = os.path.join(self.completed_dir_path, fn)
            f = open(fp, "w")
            f.write(str(digestsha1))
            f.close()

            #Upload the RCSP SHA! Digest to S3
            if settings.USE_S3:
                self.public_cert_status_sha1_url = s.store_in_s3(
                    fn, fp, bucket=settings.RCSPSHA1_BUCKET, public=True)

            #Upload the PEM and DER public certificates
            fn = "%s.pem" % (self.dns)
            key = "%s/%s/endpoints/%s" % (self.trust_anchor.owner.username,
                                          self.trust_anchor.dns, fn)

            fp = os.path.join(self.completed_dir_path, fn)
            if settings.USE_S3:
                self.public_cert_pem_url = s.store_in_s3(
                    key, fp, bucket=settings.PUBCERT_BUCKET, public=True)

                self.public_cert_pem_url = s.build_pretty_url(
                    self.public_cert_pem_url, settings.PUBCERT_BUCKET)
                self.public_cert_pem_s3 = json.dumps({
                    "bucket": settings.PUBCERT_BUCKET,
                    "key": key
                })

            fn = "%s.der" % (self.dns)
            key = "%s/%s/%s" % (self.trust_anchor.owner.username, self.dns, fn)
            fp = os.path.join(self.completed_dir_path, fn)
            #print "S3 --------------------", key, fp
            if settings.USE_S3:
                self.public_cert_der_url = s.store_in_s3(
                    key, fp, bucket=settings.PUBCERT_BUCKET, public=True)
                self.public_cert_der_url = s.build_pretty_url(
                    self.public_cert_der_url, settings.PUBCERT_BUCKET)
                self.public_cert_der_s3 = json.dumps({
                    "bucket": settings.PUBCERT_BUCKET,
                    "key": key
                })

            #Send the zip file and expire in one week
            fp = os.path.join(self.completed_dir_path, self.private_zip_name)
            key = str(self.private_zip_name)
            if settings.USE_S3:
                url = s.store_in_s3(key, fp, bucket=settings.PRIVCERT_BUCKET)

                self.presigned_zip_url = s.get_presignedurl(
                    key, bucket=settings.PRIVCERT_BUCKET)
                self.presigned_zip_s3 = json.dumps({
                    "bucket": settings.PRIVCERT_BUCKET,
                    "key": key
                })

            #send the verification email.
            msg = """
            <html>
            <head>
            </head>
            <body>
            Congratulations. Your domain bound certificate has been verified.
            Below are links to your public certificates and related status information.
            Please login into <a href="https://console.directca.org">console.directca.org</a>
            to retrieve your private certificates for this domain.
            <ul>
                <li><a href="%s">PEM File - %s </a></li>
                <li><a href="%s">DER File -  %s </a></li>
                <li><a href="%s">Status - %s </a></li>
                <li><a href="%s">Status SHA1 Digest - %s </a></li>
                <li><a href="%s">Certificate chain in JOSE x5c format - %s </a></li>
            </ul>
            
            <p>For security purposes you must
            <a href="https://console.directca.org">login</a> and download the
            private certificates within 72 hours of this email.  
            </p>
            
            </body>
            </html>
            """ % (
                self.public_cert_pem_url,
                self.public_cert_pem_url,
                self.public_cert_der_url,
                self.public_cert_der_url,
                self.public_cert_status_url,
                self.public_cert_status_url,
                self.public_cert_status_sha1_url,
                self.public_cert_status_sha1_url,
                self.public_cert_x5c_url,
                self.public_cert_x5c_url,
            )
            if settings.SEND_CA_EMAIL:
                msg = EmailMessage(
                    '[DirectCA]Your Domain-Bound Certificate has been verified',
                    msg, settings.EMAIL_HOST_USER,
                    [self.trust_anchor.owner.email, self.contact_email])
                msg.content_subtype = "html"  # Main content is now text/html
                msg.send()

            #send the verification email.
            self.verified_message_sent = True
            super(DomainBoundCertificate, self).save(**kwargs)
            return

        if self.revoke and self.status != "revoked":
            self.revoke = True
            self.status = "revoked"

            # Get the response
            rcsp_result = write_verification_message(
                self.serial_number,
                self.common_name,
                "revoked",
                self.sha1_fingerprint,
            )
            #Write it to db
            self.rcsp_response = rcsp_result
            fn = "%s.json" % (self.serial_number)
            #Write it to file
            fp = os.path.join(self.completed_dir_path, fn)

            f = open(fp, "w")
            f.write(str(rcsp_result))
            f.close()

            #Upload the RCSP file to S3
            s = SimpleS3()
            if settings.USE_S3:
                url = s.store_in_s3(fn,
                                    fp,
                                    bucket=settings.RCSP_BUCKET,
                                    public=True)

            #Calculate the SHA1 fingerprint & write it to a file
            digestsha1 = json.dumps(sha.sha1_from_filepath(fp), indent=4)
            fn = "%s-sha1.json" % (self.serial_number)
            fp = os.path.join(self.completed_dir_path, fn)
            f = open(fp, "w")
            f.write(str(digestsha1))
            f.close()

            #Upload the RCSP SHA! Digest to S3
            if settings.USE_S3:
                url = s.store_in_s3(fn,
                                    fp,
                                    bucket=settings.RCSPSHA1_BUCKET,
                                    public=True)

                #Delete all the old files:
                #PEM, DIR, ZIP
                if self.presigned_zip_s3:
                    s3info = json.loads(self.presigned_zip_s3)
                    self.presigned_zip_url = s.delete_in_s3(
                        s3info['bucket'],
                        s3info['key'],
                    )
                if self.public_cert_der_s3:
                    s3info = json.loads(self.public_cert_der_s3)
                    self.public_cert_der_url = s.delete_in_s3(
                        s3info['bucket'],
                        s3info['key'],
                    )

                if self.public_cert_pem_s3:
                    s3info = json.loads(self.public_cert_pem_s3)
                    self.public_cert_pem_url = s.delete_in_s3(
                        s3info['bucket'],
                        s3info['key'],
                    )

            # Now perform the revcation on our index and delete old files.
            revoke_from_anchor(self)
            revoke(self)

        super(DomainBoundCertificate, self).save(**kwargs)

    def delete(self, **kwargs):
        self.revoke = True
        self.status = "revoked"
        # Get the response
        rcsp_result = write_verification_message(
            self.serial_number,
            self.common_name,
            "revoked",
            self.sha1_fingerprint,
        )
        #Write it to db
        self.rcsp_response = rcsp_result
        fn = "%s.json" % (self.serial_number)
        #Write it to file
        fp = os.path.join(self.completed_dir_path, fn)

        f = open(fp, "w")
        f.write(str(rcsp_result))
        f.close()

        #Upload the RCSP file to S3
        s = SimpleS3()
        if settings.USE_S3:
            url = s.store_in_s3(fn,
                                fp,
                                bucket=settings.RCSP_BUCKET,
                                public=True)

        #Calculate the SHA1 fingerprint & write it to a file
        digestsha1 = json.dumps(sha.sha1_from_filepath(fp), indent=4)
        fn = "%s-sha1.json" % (self.serial_number)
        fp = os.path.join(self.completed_dir_path, fn)
        f = open(fp, "w")
        f.write(str(digestsha1))
        f.close()

        #Upload the RCSP SHA! Digest to S3
        if settings.USE_S3:
            url = s.store_in_s3(fn,
                                fp,
                                bucket=settings.RCSPSHA1_BUCKET,
                                public=True)
        revoke_from_anchor(self)
        revoke(self)

        super(DomainBoundCertificate, self).save(**kwargs)
Esempio n. 14
0
File: core.py Progetto: usood/nadine
class Member(models.Model):
    MAX_PHOTO_SIZE = 1024
    """A person who has used the space and may or may not have a monthly membership"""
    objects = MemberManager()

    user = models.OneToOneField(User, blank=False)
    email2 = models.EmailField("Alternate Email", blank=True, null=True)
    phone = PhoneNumberField(blank=True, null=True)
    phone2 = PhoneNumberField("Alternate Phone", blank=True, null=True)
    address1 = models.CharField(max_length=128, blank=True)
    address2 = models.CharField(max_length=128, blank=True)
    city = models.CharField(max_length=128, blank=True)
    state = models.CharField(max_length=2, blank=True)
    zipcode = models.CharField(max_length=5, blank=True)
    url_personal = models.URLField(blank=True, null=True)
    url_professional = models.URLField(blank=True, null=True)
    url_facebook = models.URLField(blank=True, null=True)
    url_twitter = models.URLField(blank=True, null=True)
    url_linkedin = models.URLField(blank=True, null=True)
    url_aboutme = models.URLField(blank=True, null=True)
    url_github = models.URLField(blank=True, null=True)
    gender = models.CharField(max_length=1,
                              choices=GENDER_CHOICES,
                              default="U")
    howHeard = models.ForeignKey(HowHeard, blank=True, null=True)
    #referred_by = models.ForeignKey(User, verbose_name="Referred By", related_name="referral", blank=True, null=True)
    industry = models.ForeignKey(Industry, blank=True, null=True)
    neighborhood = models.ForeignKey(Neighborhood, blank=True, null=True)
    has_kids = models.NullBooleanField(blank=True, null=True)
    self_employed = models.NullBooleanField(blank=True, null=True)
    company_name = models.CharField(max_length=128, blank=True, null=True)
    promised_followup = models.DateField(blank=True, null=True)
    last_modified = models.DateField(auto_now=True, editable=False)
    photo = models.ImageField(upload_to=user_photo_path, blank=True, null=True)
    tags = TaggableManager(blank=True)
    valid_billing = models.NullBooleanField(blank=True, null=True)

    @property
    def first_name(self):
        return smart_str(self.user.first_name)

    @property
    def last_name(self):
        return smart_str(self.user.last_name)

    @property
    def email(self):
        return self.user.email

    @property
    def full_name(self):
        return '%s %s' % (smart_str(
            self.user.first_name), smart_str(self.user.last_name))

    def natural_key(self):
        return [self.user.id]

    def all_bills(self):
        """Returns all of the open bills, both for this member and any bills for other members which are marked to be paid by this member."""
        from nadine.models.payment import Bill
        return Bill.objects.filter(
            models.Q(member=self)
            | models.Q(paid_by=self)).order_by('-bill_date')

    def open_bills(self):
        """Returns all of the open bills, both for this member and any bills for other members which are marked to be paid by this member."""
        from nadine.models.payment import Bill
        return Bill.objects.filter(
            models.Q(member=self) | models.Q(paid_by=self)).filter(
                transactions=None).order_by('bill_date')

    def open_bill_amount(self):
        total = 0
        for b in self.open_bills():
            total = total + b.amount
        return total

    def open_bills_amount(self):
        """Returns the amount of all of the open bills, both for this member and any bills for other members which are marked to be paid by this member."""
        from nadine.models.payment import Bill
        return Bill.objects.filter(
            models.Q(member=self)
            | models.Q(paid_by=self)).filter(transactions=None).aggregate(
                models.Sum('amount'))['amount__sum']

    def open_xero_invoices(self):
        from nadine.xero_api import XeroAPI
        xero_api = XeroAPI()
        return xero_api.get_open_invoices(self.user)

    def pay_bills_form(self):
        from staff.forms import PayBillsForm
        return PayBillsForm(initial={
            'member_id': self.id,
            'amount': self.open_bills_amount
        })

    def last_bill(self):
        """Returns the latest Bill, or None if the member has not been billed.
        NOTE: This does not (and should not) return bills which are for other members but which are to be paid by this member."""
        from nadine.models.payment import Bill
        bills = Bill.objects.filter(member=self)
        if len(bills) == 0:
            return None
        return bills[0]

    def membership_history(self):
        return Membership.objects.filter(member=self).order_by(
            '-start_date', 'end_date')

    def last_membership(self):
        """Returns the latest membership, even if it has an end date, or None if none exists"""
        memberships = Membership.objects.filter(member=self).order_by(
            '-start_date', 'end_date')[0:]
        if memberships == None or len(memberships) == 0:
            return None
        return memberships[0]

    def active_membership(self):
        for membership in self.membership_history():
            if membership.is_active():
                return membership
        return None

    def membership_for_day(self, day):
        return Membership.objects.active_memberships(target_date=day).filter(
            member=self).first()

    def activity_this_month(self, test_date=None):
        if not test_date:
            test_date = date.today()

        membership = self.active_membership()
        if membership:
            if membership.guest_of:
                # Return host's activity
                host = membership.guest_of
                return host.activity_this_month()
            month_start = membership.prev_billing_date(test_date)
        else:
            # Just go back one month from this date since there isn't a membership to work with
            month_start = test_date - MonthDelta(1)
        # print month_start

        activity = []
        for m in [self] + self.guests():
            for l in DailyLog.objects.filter(member=m,
                                             payment='Bill',
                                             visit_date__gte=month_start):
                activity.append(l)
        for l in DailyLog.objects.filter(guest_of=self,
                                         payment='Bill',
                                         visit_date__gte=month_start):
            activity.append(l)
        return activity

    def activity(self):
        return DailyLog.objects.filter(member=self)

    def paid_count(self):
        return self.activity().filter(payment='Bill').count()

    def first_visit(self):
        if Membership.objects.filter(member=self).count() > 0:
            return Membership.objects.filter(
                member=self).order_by('start_date')[0].start_date
        else:
            if DailyLog.objects.filter(member=self).count() > 0:
                return DailyLog.objects.filter(
                    member=self).order_by('visit_date')[0].visit_date
            else:
                return None

    def duration(self):
        return relativedelta(timezone.now().date(), self.first_visit())

    def duration_str(self, include_days=False):
        retval = ""
        delta = self.duration()
        if delta.years:
            if delta.years == 1:
                retval = "1 year"
            else:
                retval = "%d years" % delta.years
            if delta.months or delta.days:
                retval += " and "
        if delta.months:
            if delta.months == 1:
                retval += "1 month"
            else:
                retval += "%d months" % delta.months
            if include_days and delta.days:
                retval += " and "
        if include_days and delta.days:
            if delta.days == 1:
                retval += "1 day"
            else:
                retval += "%d days" % delta.days
        return retval

    def is_anniversary(self):

        return

    def host_daily_logs(self):
        return DailyLog.objects.filter(guest_of=self).order_by('-visit_date')

    def has_file_uploads(self):
        return FileUpload.objects.filter(user=self.user).count() > 0

    def has_file(self, doc_type):
        return FileUpload.objects.filter(user=self.user,
                                         document_type=doc_type).count() > 0

    def file_uploads(self):
        files = {}
        # Only want the latest one if there are duplicates
        for f in FileUpload.objects.filter(
                user=self.user).order_by('uploadTS').reverse():
            files[f.name] = f
        return files.values()

    def files_by_type(self):
        files = {}
        # Only want the latest one if there are duplicates
        for f in FileUpload.objects.filter(
                user=self.user).order_by('uploadTS').reverse():
            files[f.document_type] = f
        return files

    def alerts_by_key(self, include_resolved=False):
        from nadine.models.alerts import MemberAlert
        if include_resolved:
            alerts = MemberAlert.objects.filter(user=self.user)
        else:
            alerts = MemberAlert.objects.filter(user=self.user,
                                                resolved_ts__isnull=True,
                                                muted_ts__isnull=True)
        alerts_by_key = {}
        for alert in alerts:
            if alert.key in alerts_by_key:
                alerts_by_key[alert.key].append(alert)
            else:
                alerts_by_key[alert.key] = [alert]
        return alerts_by_key

    def alerts(self):
        from nadine.models.alerts import MemberAlert
        return MemberAlert.objects.filter(
            user=self.user).order_by('-created_ts')

    def open_alerts(self):
        from nadine.models.alerts import MemberAlert
        return MemberAlert.objects.filter(
            user=self.user, resolved_ts__isnull=True,
            muted_ts__isnull=True).order_by('-created_ts')

    def resolve_alerts(self, alert_key, resolved_by=None):
        logger.debug("resolve_alerts: user=%s, key=%s, resolved_by=%s" %
                     (self.user, alert_key, resolved_by))
        from nadine.models.alerts import MemberAlert
        alerts = MemberAlert.objects.filter(
            user=self.user,
            key=alert_key,
            resolved_ts__isnull=True,
            muted_ts__isnull=True).order_by('-created_ts')
        if alerts:
            for alert in alerts:
                alert.resolve(resolved_by)

    def member_since(self):
        first = self.first_visit()
        if first == None:
            return None
        return timezone.localtime(timezone.now()) - datetime.combine(
            first, time(0, 0, 0))

    def last_visit(self):
        if DailyLog.objects.filter(member=self).count() > 0:
            return DailyLog.objects.filter(
                member=self).latest('visit_date').visit_date
        else:
            if Membership.objects.filter(member=self,
                                         end_date__isnull=False).count() > 0:
                return Membership.objects.filter(
                    member=self,
                    end_date__isnull=False).latest('end_date').end_date
            else:
                return None

    def membership_type(self):
        active_membership = self.active_membership()
        if active_membership:
            return active_membership.membership_plan
        else:
            last_monthly = self.last_membership()
            if last_monthly:
                return "Ex" + str(last_monthly.membership_plan)

        # Now check daily logs
        drop_ins = DailyLog.objects.filter(member=self).count()
        if drop_ins == 0:
            return "New User"
        elif drop_ins == 1:
            return "First Day"
        else:
            return "Drop-in"

    def is_active(self):
        m = self.active_membership()
        return m is not None

    def has_desk(self):
        m = self.active_membership()
        if not m:
            return False
        if m.is_active():
            return m.has_desk
        return False

    def is_guest(self):
        m = self.active_membership()
        if m and m.is_active() and m.guest_of:
            return m.guest_of
        return None

    def has_valid_billing(self):
        host = self.is_guest()
        if host:
            return host.has_valid_billing()
        if self.valid_billing is None:
            logger.debug("%s: Null Valid Billing" % self)
            if self.has_new_card():
                logger.debug("%s: Found new card.  Marking billing valid." %
                             self)
                self.valid_billing = True
                self.save()
            else:
                self.valid_billing = False
        return self.valid_billing

    def has_billing_profile(self):
        if usaepay.getAllCustomers(self.user.username):
            return True
        return False

    def has_new_card(self):
        # Check for a new card.  WARNING: kinda expensive
        return usaepay.has_new_card(self.user.username)

    def guests(self):
        guests = []
        for membership in Membership.objects.filter(guest_of=self):
            if membership.is_active():
                guests.append(membership.member)
        return guests

    def deposits(self):
        return SecurityDeposit.objects.filter(member=self)

    def __str__(self):
        return '%s %s' % (smart_str(
            self.user.first_name), smart_str(self.user.last_name))

    def usaepay_auth(self):
        return usaepay.get_auth_code(self.user.username)

    def auto_bill_enabled(self):
        return usaepay.auto_bill_enabled(self.user.username)

    def member_notes(self):
        return MemberNote.objects.filter(member=self)

    def special_days(self):
        return SpecialDay.objects.filter(member=self)

    def membership_days(self):
        total_days = 0
        for membership in self.membership_history():
            end = membership.end_date
            if not end:
                end = timezone.now().date()
            diff = end - membership.start_date
            days = diff.days
            total_days = total_days + days
        return total_days

    def average_bill(self):
        from nadine.models.payment import Bill
        bills = Bill.objects.filter(member=self)
        if bills:
            bill_totals = 0
            for b in bills:
                bill_totals = bill_totals + b.amount
            return bill_totals / len(bills)
        return 0

    def is_manager(self):
        if hasattr(settings, 'TEAM_MEMBERSHIP_PLAN'):
            management_plan = MembershipPlan.objects.filter(
                name=settings.TEAM_MEMBERSHIP_PLAN).first()
            if management_plan:
                active_membership = self.active_membership()
                if active_membership:
                    return active_membership.membership_plan == management_plan
        return False

    @models.permalink
    def get_absolute_url(self):
        return ('staff.views.member_detail', (), {'member_id': self.id})

    class Meta:
        app_label = 'nadine'
        ordering = ['user__first_name', 'user__last_name']
        get_latest_by = "last_modified"
Esempio n. 15
0
class Member(models.Model):
	"""A person who has used the space and may or may not have a monthly membership"""
	objects = MemberManager()

	user = models.ForeignKey(User, unique=True, blank=False, related_name="user")
	email2 = models.EmailField("Alternate Email", blank=True, null=True)
	phone = PhoneNumberField(blank=True, null=True)
	phone2 = PhoneNumberField("Alternate Phone", blank=True, null=True)
	address1 = models.CharField(max_length = 128, blank = True)
	address2 = models.CharField(max_length = 128, blank = True)
	city = models.CharField(max_length = 128, blank = True)
	state = models.CharField(max_length = 2, blank = True)
	zipcode = models.CharField(max_length = 5, blank = True)
	url_personal = models.URLField(blank=True, null=True)
	url_professional = models.URLField(blank=True, null=True)
	url_facebook = models.URLField(blank=True, null=True)
	url_twitter = models.URLField(blank=True, null=True)
	url_biznik = models.URLField(blank=True, null=True)
	url_linkedin = models.URLField(blank=True, null=True)
	url_aboutme = models.URLField(blank=True, null=True)
	url_github = models.URLField(blank=True, null=True)
	gender = models.CharField(max_length=1, choices=GENDER_CHOICES, default="U")
	howHeard = models.ForeignKey(HowHeard, blank=True, null=True)
	#referred_by = models.ForeignKey(User, verbose_name="Referred By", related_name="referred_by", blank=True, null=True)
	industry = models.ForeignKey(Industry, blank=True, null=True)
	neighborhood = models.ForeignKey(Neighborhood, blank=True, null=True)
	has_kids = models.NullBooleanField(blank=True, null=True)
	self_employed = models.NullBooleanField(blank=True, null=True)
	company_name = models.CharField(max_length=128, blank=True, null=True)
	promised_followup = models.DateField(blank=True, null=True)
	last_modified = models.DateField(auto_now=True, editable=False)
	notes = models.TextField(blank=True, null=True)
	photo = models.ImageField(upload_to='member_photo', blank=True, null=True)
	tags = TaggableManager(blank=True)
	valid_billing = models.BooleanField(default=False)

	@property
	def first_name(self): return smart_str(self.user.first_name)

	@property
	def last_name(self): return smart_str(self.user.last_name)

	@property
	def email(self): return self.user.email

	@property
	def full_name(self):
		return '%s %s' % (smart_str(self.user.first_name), smart_str(self.user.last_name))

	def natural_key(self): return [self.user.id]

	def all_bills(self):
		"""Returns all of the open bills, both for this member and any bills for other members which are marked to be paid by this member."""
		return Bill.objects.filter(models.Q(member=self) | models.Q(paid_by=self)).order_by('-created')

	def open_bills(self):
		"""Returns all of the open bills, both for this member and any bills for other members which are marked to be paid by this member."""
		return Bill.objects.filter(models.Q(member=self) | models.Q(paid_by=self)).filter(transactions=None).order_by('created')

	def open_bills_amount(self):
		"""Returns the amount of all of the open bills, both for this member and any bills for other members which are marked to be paid by this member."""
		return Bill.objects.filter(models.Q(member=self) | models.Q(paid_by=self)).filter(transactions=None).aggregate(models.Sum('amount'))['amount__sum']

	def pay_bills_form(self):
		from forms import PayBillsForm
		return PayBillsForm(initial={'member_id':self.id, 'amount':self.open_bills_amount })

	def last_bill(self):
		"""Returns the latest Bill, or None if the member has not been billed.
		NOTE: This does not (and should not) return bills which are for other members but which are to be paid by this member."""
		bills = Bill.objects.filter(member=self)
		if len(bills) == 0: return None
		return bills[0]

	def last_membership(self):
		"""Returns the latest membership, even if it has an end date, or None if none exists"""
		memberships = Membership.objects.filter(member=self).order_by('-start_date', 'end_date')[0:]
		if memberships == None or len(memberships) == 0: return None
		return memberships[0]

	def active_membership(self):
		for membership in Membership.objects.filter(member=self).order_by('-start_date', 'end_date'):
			if membership.is_active():
				return membership
		return None

	def activity_this_month(self, test_date=date.today()):
		membership = self.active_membership()
		if not membership: 
			# Not a member
			return None
		if membership.guest_of:
			# Return host's activity
			host = membership.guest_of
			return host.activity_this_month()
		month_start = membership.prev_billing_date(test_date)
		print month_start
		activity = []
		for m in [self] + self.guests():
			for l in DailyLog.objects.filter(member=m, payment='Bill', visit_date__gte=month_start):
				activity.append(l)
		for l in DailyLog.objects.filter(guest_of=self, payment='Bill', visit_date__gte=month_start):
			activity.append(l)
		return activity

	def paid_count(self):
		return DailyLog.objects.filter(member=self, payment='Bill').count()

	def first_visit(self):
		if Membership.objects.filter(member=self).count() > 0:
			return Membership.objects.filter(member=self).order_by('start_date')[0].start_date
		else:
			if DailyLog.objects.filter(member=self).count() > 0:
				return DailyLog.objects.filter(member=self).order_by('visit_date')[0].visit_date
			else:
				return None

	def host_daily_logs(self):
		return DailyLog.objects.filter(guest_of=self).order_by('-visit_date')

	def member_since(self):
		first = self.first_visit()
		if first == None: return None
		return timezone.localtime(timezone.now()) - datetime.combine(first, time(0,0,0))

	def last_visit(self):
		if DailyLog.objects.filter(member=self).count() > 0:
			return DailyLog.objects.filter(member=self).latest('visit_date').visit_date
		else:
			if Membership.objects.filter(member=self, end_date__isnull=False).count() > 0:
				return Membership.objects.filter(member=self, end_date__isnull=False).latest('end_date').end_date
			else:
				return None

	def membership_type(self):
		# First check for existing monthly
		memberships = Membership.objects.filter(member=self)
		if self.last_membership():
			last_monthly = self.last_membership()
			if last_monthly.end_date == None or last_monthly.end_date > timezone.now().date():
				return last_monthly.membership_plan
			else:
				return "Ex" + str(last_monthly.membership_plan)

		# Now check daily logs
		drop_ins = DailyLog.objects.filter(member=self).count()
	 	if drop_ins == 0:
			return "New User"
		elif drop_ins == 1:
			return "First Day"
		else:
			return "Drop-in"

	def is_active(self):
		m = self.active_membership()
		return m is not None

	def has_desk(self):
		m = self.active_membership()
		if not m: return False
		if m.is_active():
			return m.has_desk
		return False

	def is_guest(self):
		m = self.active_membership()
		if m and m.is_active() and m.guest_of:
			return m.guest_of
		return None

	def has_valid_billing(self):
		host = self.is_guest()
		if host:
			return host.has_valid_billing()
		return self.valid_billing
		
	def guests(self):
		guests = []
		for membership in Membership.objects.filter(guest_of=self):
			if membership.is_active():
				guests.append(membership.member)
		return guests

	def deposits(self):
		return SecurityDeposit.objects.filter(member=self)
		
	def onboard_tasks_status(self):
		"""
		Returns an array of tuples: (Onboard_Task, Onboard_Task_Completed) for this member.
		Onboard_Task_Completed may be None.
		"""
		return [(task, Onboard_Task_Completed.objects.for_member(task, self)) for task in Onboard_Task.objects.all()]

	def onboard_tasks_to_complete(self):
		return Onboard_Task.objects.count() - Onboard_Task_Completed.objects.filter(member=self).count()

	def qualifies_for_exit_tasks(self):
		last_log = self.last_membership()
		if not last_log or last_log.end_date == None: return False
		return last_log.end_date < timezone.now().date()

	def exit_tasks_status(self):
		"""
		Returns an array of tuples: (ExitTask, ExitTaskCompleted) for this member.
		ExitCompleted may be None.
		"""
		if not self.qualifies_for_exit_tasks(): return []
		return [(task, ExitTaskCompleted.objects.for_member(task, self)) for task in ExitTask.objects.all()]

	def exit_tasks_to_complete(self):
		if not self.qualifies_for_exit_tasks(): return 0
		return ExitTask.objects.count() - ExitTaskCompleted.objects.filter(member=self).count()

	def __str__(self): return '%s %s' % (smart_str(self.user.first_name), smart_str(self.user.last_name))

	@models.permalink
	def get_absolute_url(self):
		return ('staff.views.member_detail', (), { 'member_id':self.id })

	class Meta:
		ordering = ['user__first_name', 'user__last_name']
		get_latest_by = "last_modified"
Esempio n. 16
0
class Invoice(models.Model):
	invoice_date = models.DateTimeField(auto_now_add=True)
	paid_date = models.DateTimeField(blank=True, null=True)
	sent_date = models.DateTimeField(blank=True, null=True)
	customer = models.ForeignKey('customer.Customer', related_name='invoiced')
	owner = models.ForeignKey(User, null=True, on_delete=models.SET_NULL, related_name='owns')
	shorturl = models.CharField(max_length=10, editable=False)
	#duplicate fields from customer so that we can archive the invoice.
	# If the customers' info changes in the future, we don't want all old invoices to update too
	first_name = models.CharField(max_length=30, blank=True, null=True)
	last_name = models.CharField(max_length=30, blank=True, null=True)
	street1 = models.CharField(max_length=60, verbose_name="Address 1", editable=False)
	street2 = models.CharField(max_length=60, blank=True, verbose_name="Address 2", editable=False)
	city = models.CharField(max_length=30, editable=False)
	state = USPostalCodeField()
	zip_code = models.CharField(max_length=10, verbose_name="Zip Code")
	email = models.CharField(max_length=65, editable=False)
	phone = PhoneNumberField()


	def __unicode__(self):
		return "%s #%d (%s)" % (self.customer.get_full_name(), self.pk, self.shorturl)

	def _get_grand_total(self):
		total = Decimal("0.0")
		taxable = Decimal("0.0")
		for li in self.lineitems.all():
			if li.taxable:
				taxable += li.total
			else:
				total += li.total
		taxable = taxable * Decimal(settings.TAX_RATE)
		total += taxable
		return total.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)

	def _get_taxable_total(self):
		total = Decimal("0.0")
		for li in self.lineitems.all():
			if li.taxable:
				total += li.total
		return total.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)

	def _get_total_tax(self):
		total = Decimal("0.0")
		inv_tax_rate = Decimal(settings.TAX_RATE) - Decimal("1.0")
		for li in self.lineitems.all():
			if li.taxable:
				total += Decimal(li.unit_price * li.quantity)
		total = total * inv_tax_rate
		return total.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)

	def _get_sub_total(self):
		total = Decimal("0.0")
		for li in self.lineitems.all():
				total += Decimal(li.unit_price * li.quantity)
		return total.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)

	grand_total = property(_get_grand_total)
	total_tax = property(_get_total_tax)
	taxable_total = property(_get_taxable_total)
	sub_total = property(_get_sub_total)

	def _is_paid(self):
		return True if self.paid_date else False
	_is_paid.admin_order_field = 'paid_date'
	_is_paid.boolean = True
	_is_paid.short_description = 'Paid?'

	is_paid = property(_is_paid)

	def num_to_base56(self, num):
		#list of randomized, url-safe, unambiguous chars
		charList = 'x5d8j9A3BmCZDsEtFGwHpJuKLaMkNzPQnS6TvUhV2WfX4cYb7egiqRry'
		if num > 56:
			return self.num_to_base56(math.floor(int(num)/56)) + charList[int(num) % 56]
		else:
			return charList[int(num)]

	def save(self, force_insert=False, force_update=False):
		if self.shorturl is None or self.shorturl == '':
			notpk = int(time.mktime(datetime.datetime.now().timetuple()))
			urlStr = self.num_to_base56(notpk)
			while len(urlStr) < 5:
				urlStr = self.num_to_base56('0') + urlStr
			self.shorturl = urlStr

		if self.pk is None:
			linked_customer = self.customer
			self.first_name = linked_customer.first_name
			self.last_name = linked_customer.last_name
			self.street1 = linked_customer.street1
			self.street2 = linked_customer.street2
			self.city = linked_customer.city
			self.state = linked_customer.state
			self.zip_code = linked_customer.zip_code
			self.phone = linked_customer.phone
			self.email = linked_customer.email
		super(Invoice, self).save(force_insert, force_update)
Esempio n. 17
0
class Organization(models.Model):
    name = models.CharField(max_length=255, unique=True)
    uuid = models.UUIDField(unique=True, db_index=True, default=uuid4)
    address = models.CharField(max_length=255, null=True, blank=True)
    address1 = models.CharField(max_length=255, null=True, blank=True)
    city = models.CharField(max_length=255, null=True, blank=True)
    state = models.CharField(max_length=80, null=True, blank=True)
    zip = models.CharField(max_length=25, null=True, blank=True)
    country = models.CharField(max_length=80,
                               null=True,
                               blank=True,
                               default='US')
    fax = PhoneNumberField(null=True, blank=True)
    phone = PhoneNumberField(null=True, blank=True)
    locale = models.CharField(max_length=2,
                              null=True,
                              blank=True,
                              default='en')
    removed = models.DateField(null=True)
    timezone = TimeZoneField(default=settings.TIME_ZONE)
    website = models.URLField(null=True, blank=True)

    is_active = models.BooleanField(default=True)

    objects = ActiveManager()

    class Meta:
        ordering = ['name']
        db_table = 'kala_companies'

    def set_active(self, active):
        self.is_active = active
        for person in self.user_set.all():
            person.set_active(active)

        for project in Project.objects.filter(organization=self):
            project.set_active(active)

        if not self.is_active:
            self.removed = datetime.date.today()
        self.save()

    def get_projects(self, user):
        if user.is_superuser:
            return Project.objects.active().filter(organization=self)
        else:
            return Project.objects.active().filter(
                id__in=user.get_projects().values_list('id', flat=True),
                organization=self)

    def __str__(self):
        return self.name

    def can(self, user, _permissions):
        if user.is_superuser:
            return True

        return True if OrganizationPermission.objects.filter(
            permission__in=Permission.objects.filter(
                codename__in=_permissions,
                content_type__app_label='organizations'),
            user=user,
            organization=self).exists() else False

    def can_create(self, user):
        return self.can(user, ['can_create', 'can_invite', 'can_manage'])

    def can_invite(self, user):
        return self.can(user, ['can_invite', 'can_manage'])

    def can_manage(self, user):
        return self.can(user, ['can_manage'])

    def add_permission(self, user, permission):
        OrganizationPermission.objects.get_or_create(
            permission=Permission.objects.get(
                codename=permission, content_type__app_label='organizations'),
            user=user,
            organization=self)

    def add_create(self, user):
        self.add_permission(user, 'can_create')

    def add_invite(self, user):
        self.add_permission(user, 'can_invite')

    def add_manage(self, user):
        self.add_permission(user, 'can_manage')

    def delete_permission(self, user, permission):
        try:
            OrganizationPermission.objects.get(
                permission=Permission.objects.get(
                    codename=permission,
                    content_type__app_label='organizations'),
                user=user,
                organization=self).delete()
        except OrganizationPermission.DoesNotExist:
            return False

    def delete_create(self, user):
        self.delete_permission(user, 'can_create')

    def delete_invite(self, user):
        self.delete_permission(user, 'can_invite')

    def delete_manage(self, user):
        self.delete_permission(user, 'can_manage')
Esempio n. 18
0
class UserProfile(models.Model):
    MAX_PHOTO_SIZE = 1024

    user = models.OneToOneField(User, blank=False, related_name="profile")
    phone = PhoneNumberField(blank=True, null=True)
    phone2 = PhoneNumberField("Alternate Phone", blank=True, null=True)
    address1 = models.CharField(max_length=128, blank=True)
    address2 = models.CharField(max_length=128, blank=True)
    city = models.CharField(max_length=128, blank=True)
    state = models.CharField(max_length=2, blank=True)
    zipcode = models.CharField(max_length=16, blank=True)
    bio = models.TextField(blank=True, null=True)
    public_profile = models.BooleanField(default=False)
    gender = models.CharField(max_length=1, choices=GENDER_CHOICES, default="U")
    howHeard = models.ForeignKey(HowHeard, blank=True, null=True)
    #referred_by = models.ForeignKey(User, verbose_name="Referred By", related_name="referral", blank=True, null=True)
    industry = models.ForeignKey(Industry, blank=True, null=True)
    neighborhood = models.ForeignKey(Neighborhood, blank=True, null=True)
    has_kids = models.NullBooleanField(blank=True, null=True)
    self_employed = models.NullBooleanField(blank=True, null=True)
    last_modified = models.DateField(auto_now=True, editable=False)
    photo = models.ImageField(upload_to=user_photo_path, blank=True, null=True)
    tags = TaggableManager(blank=True)
    valid_billing = models.NullBooleanField(blank=True, null=True)
    websites = models.ManyToManyField(Website, blank=True)

    @property
    def url_personal(self):
        return self.websites.filter(url_type__name="personal").first()

    @property
    def url_professional(self):
        return self.websites.filter(url_type__name="professional").first()

    @property
    def url_facebook(self):
        return self.websites.filter(url_type__name="facebook").first()

    @property
    def url_twitter(self):
        return self.websites.filter(url_type__name="twitter").first()

    @property
    def url_linkedin(self):
        return self.websites.filter(url_type__name="linkedin").first()

    @property
    def url_github(self):
        return self.websites.filter(url_type__name="github").first()

    def save_url(self, url_type, url_value):
        if url_type and url_value:
            w = self.websites.filter(url_type__name=url_type).first()
            if w:
                w.url = url_value
                w.save()
            else:
                t = URLType.objects.get(name=url_type)
                self.websites.create(url_type=t, url=url_value)

    def active_organization_memberships(self, on_date=None):
        if not on_date:
            on_date = timezone.now().date()
        future = Q(end_date__isnull=True)
        unending = Q(end_date__gte=on_date)
        return self.user.organizationmember_set.filter(start_date__lte=on_date).filter(future | unending)

    def past_organization_memberships(self, on_date=None):
        if not on_date:
            on_date = timezone.now().date()
        return self.user.organizationmember_set.filter(end_date__lte=on_date)

    def active_organizations(self, on_date=None):
        active = self.active_organization_memberships(on_date)
        return Organization.objects.filter(id__in=active.values('organization'))

    def all_bills(self):
        """Returns all of the open bills, both for this user and any bills for other members which are marked to be paid by this member."""
        return Bill.objects.filter(models.Q(user=self.user) | models.Q(paid_by=self.user)).order_by('-bill_date')

    def open_bills(self):
        """Returns all of the open bills, both for this user and any bills for other members which are marked to be paid by this member."""
        return Bill.objects.filter(models.Q(user=self.user) | models.Q(paid_by=self.user)).filter(transactions=None).order_by('bill_date')

    def open_bill_amount(self):
        total = 0
        for b in self.open_bills():
            total = total + b.amount
        return total

    def open_bills_amount(self):
        """Returns the amount of all of the open bills, both for this member and any bills for other members which are marked to be paid by this member."""
        return Bill.objects.filter(models.Q(user=self.user) | models.Q(paid_by=self.user)).filter(transactions=None).aggregate(models.Sum('amount'))['amount__sum']

    def open_xero_invoices(self):
        from nadine.utils.xero_api import XeroAPI
        xero_api = XeroAPI()
        return xero_api.get_open_invoices(self.user)

    def pay_bills_form(self):
        from nadine.forms import PayBillsForm
        return PayBillsForm(initial={'username': self.user.username, 'amount': self.open_bills_amount})

    def last_bill(self):
        """Returns the latest Bill, or None if the member has not been billed.
        NOTE: This does not (and should not) return bills which are for other members but which are to be paid by this member."""
        bills = Bill.objects.filter(user=self.user)
        if len(bills) == 0:
            return None
        return bills[0]

    def membership_history(self):
        return Membership.objects.filter(user=self.user).order_by('-start_date', 'end_date')

    def membership_on_date(self, day):
        return Membership.objects.filter(user=self.user, start_date__lte=day).filter(Q(end_date__isnull=True) | Q(end_date__gte=day)).first()

    def last_membership(self):
        """Returns the latest membership, even if it has an end date, or None if none exists"""
        memberships = Membership.objects.filter(user=self.user).order_by('-start_date', 'end_date')[0:]
        if memberships == None or len(memberships) == 0:
            return None
        return memberships[0]

    def active_membership(self):
        for membership in self.membership_history():
            if membership.is_active():
                return membership
        return None

    def membership_for_day(self, day):
        return Membership.objects.active_memberships(target_date=day).filter(user=self.user).first()

    def activity_this_month(self, test_date=None):
        if not test_date:
            test_date = date.today()

        membership = self.active_membership()
        if membership:
            if membership.paid_by:
                # Return host's activity
                host = membership.paid_by
                return host.profile.activity_this_month()
            month_start = membership.prev_billing_date(test_date)
        else:
            # Just go back one month from this date since there isn't a membership to work with
            month_start = test_date - MonthDelta(1)

        activity = []
        for h in [self.user] + self.guests():
            for l in CoworkingDay.objects.filter(user=h, payment='Bill', visit_date__gte=month_start).exclude(paid_by__isnull=False):
                activity.append(l)
        for l in CoworkingDay.objects.filter(paid_by=self.user, payment='Bill', visit_date__gte=month_start):
            activity.append(l)
        return activity

    def activity(self):
        return CoworkingDay.objects.filter(user=self.user)

    def paid_count(self):
        return self.activity().filter(payment='Bill').count()

    def first_visit(self):
        if Membership.objects.filter(user=self.user).count() > 0:
            return Membership.objects.filter(user=self.user).order_by('start_date')[0].start_date
        else:
            if CoworkingDay.objects.filter(user=self.user).count() > 0:
                return CoworkingDay.objects.filter(user=self.user).order_by('visit_date')[0].visit_date
            else:
                return None

    def all_emails(self):
        # Done in two queries so that the primary email address is always on top.
        primary = self.user.emailaddress_set.filter(is_primary=True)
        non_primary = self.user.emailaddress_set.filter(is_primary=False)
        return list(primary) + list(non_primary)

    def non_primary_emails(self):
        return self.user.emailaddress_set.filter(is_primary=False)

    def duration(self):
        return relativedelta(timezone.now().date(), self.first_visit())

    def duration_str(self, include_days=False):
        retval = ""
        delta = self.duration()
        if delta.years:
            if delta.years == 1:
                retval = "1 year"
            else:
                retval = "%d years" % delta.years
            if delta.months or delta.days:
                retval += " and "
        if delta.months:
            if delta.months == 1:
                retval += "1 month"
            else:
                retval += "%d months" % delta.months
            if include_days and delta.days:
                retval += " and "
        if include_days and delta.days:
            if delta.days == 1:
                retval += "1 day"
            else:
                retval += "%d days" % delta.days
        return retval

    def hosted_days(self):
        return CoworkingDay.objects.filter(paid_by=self.user).order_by('-visit_date')

    def has_file_uploads(self):
        return FileUpload.objects.filter(user=self.user).count() > 0

    def has_file(self, doc_type):
        return FileUpload.objects.filter(user=self.user, document_type=doc_type).count() > 0

    def file_uploads(self):
        files = {}
        # Only want the latest one if there are duplicates
        for f in FileUpload.objects.filter(user=self.user).order_by('uploadTS').reverse():
            files[f.name] = f
        return files.values()

    def files_by_type(self):
        files = {}
        # Only want the latest one if there are duplicates
        for f in FileUpload.objects.filter(user=self.user).order_by('uploadTS').reverse():
            files[f.document_type] = f
        return files

    def alerts_by_key(self, include_resolved=False):
        from nadine.models.alerts import MemberAlert
        if include_resolved:
            alerts = MemberAlert.objects.filter(user=self.user)
        else:
            alerts = MemberAlert.objects.filter(user=self.user, resolved_ts__isnull=True, muted_ts__isnull=True)
        alerts_by_key = {}
        for alert in alerts:
            if alert.key in alerts_by_key:
                alerts_by_key[alert.key].append(alert)
            else:
                alerts_by_key[alert.key] = [alert]
        return alerts_by_key

    def alerts(self):
        from nadine.models.alerts import MemberAlert
        return MemberAlert.objects.filter(user=self.user).order_by('-created_ts')

    def open_alerts(self):
        from nadine.models.alerts import MemberAlert
        return MemberAlert.objects.filter(user=self.user, resolved_ts__isnull=True, muted_ts__isnull=True).order_by('-created_ts')

    def resolve_alerts(self, alert_key, resolved_by=None):
        logger.debug("resolve_alerts: user=%s, key=%s, resolved_by=%s" % (self.user, alert_key, resolved_by))
        from nadine.models.alerts import MemberAlert
        alerts = MemberAlert.objects.filter(user=self.user, key=alert_key, resolved_ts__isnull=True, muted_ts__isnull=True).order_by('-created_ts')
        if alerts:
            for alert in alerts:
                alert.resolve(resolved_by)

    def member_since(self):
        first = self.first_visit()
        if first == None:
            return None
        return timezone.localtime(timezone.now()) - datetime.combine(first, time(0, 0, 0))

    def last_visit(self):
        if CoworkingDay.objects.filter(user=self.user).count() > 0:
            return CoworkingDay.objects.filter(user=self.user).latest('visit_date').visit_date
        else:
            if Membership.objects.filter(user=self.user, end_date__isnull=False).count() > 0:
                return Membership.objects.filter(user=self.user, end_date__isnull=False).latest('end_date').end_date
            else:
                return None

    def membership_type(self):
        active_membership = self.active_membership()
        if active_membership:
            return active_membership.membership_plan
        else:
            last_monthly = self.last_membership()
            if last_monthly:
                return "Ex" + str(last_monthly.membership_plan)

        # Now check daily logs
        drop_ins = CoworkingDay.objects.filter(user=self.user).count()
        if drop_ins == 0:
            return "New User"
        elif drop_ins == 1:
            return "First Day"
        else:
            return "Drop-in"

    def is_active(self):
        m = self.active_membership()
        return m is not None

    def has_desk(self, target_date=None):
        if not target_date:
            target_date = timezone.now().date()
        m = self.membership_on_date(target_date)
        return m and m.has_desk

    def is_guest(self):
        m = self.active_membership()
        if m and m.is_active() and m.paid_by:
            return m.paid_by
        return None

    def guests(self):
        guests = []
        for membership in Membership.objects.filter(paid_by=self.user):
            if membership.is_active():
                guests.append(membership.user)
        return guests

    def has_valid_billing(self):
        host = self.is_guest()
        if host and host != self.user:
            return host.profile.has_valid_billing()
        if self.valid_billing is None:
            logger.debug("%s: Null Valid Billing" % self)
            if self.has_new_card():
                logger.debug("%s: Found new card.  Marking billing valid." % self)
                self.valid_billing = True
                self.save()
            else:
                self.valid_billing = False
        return self.valid_billing

    def has_billing_profile(self):
        try:
            api = PaymentAPI()
            if api.get_customers(self.user.username):
                return True
        except Exception:
            pass
        return False

    def has_new_card(self):
        # Check for a new card.  WARNING: kinda expensive
        try:
            api = PaymentAPI
            return api.has_new_card(self.user.username)
        except Exception:
            pass
        return False

    # TODO - Remove
    def deposits(self):
        return SecurityDeposit.objects.filter(user=self.user)

    def __str__(self): return '%s %s' % (smart_str(self.user.first_name), smart_str(self.user.last_name))

    def auto_bill_enabled(self):
        if not hasattr(settings, 'USA_EPAY_KEY'):
            return None
        api = PaymentAPI()
        return api.auto_bill_enabled(self.user.username)

    # TODO - Remove
    def member_notes(self):
        return MemberNote.objects.filter(user=self.user)

    # TODO - Remove
    def special_days(self):
        return SpecialDay.objects.filter(user=self.user)

    def membership_days(self):
        total_days = 0
        for membership in self.membership_history():
            end = membership.end_date
            if not end:
                end = timezone.now().date()
            diff = end - membership.start_date
            days = diff.days
            total_days = total_days + days
        return total_days

    def average_bill(self):
        from nadine.models.payment import Bill
        bills = Bill.objects.filter(user=self.user)
        if bills:
            bill_totals = 0
            for b in bills:
                bill_totals = bill_totals + b.amount
            return bill_totals / len(bills)
        return 0

    def is_manager(self):
        if self.user.is_staff: return True
        if hasattr(settings, 'TEAM_MEMBERSHIP_PLAN'):
            management_plan = MembershipPlan.objects.filter(name=settings.TEAM_MEMBERSHIP_PLAN).first()
            if management_plan:
                active_membership = self.active_membership()
                if active_membership:
                    return active_membership.membership_plan == management_plan
        return False

    class Meta:
        app_label = 'nadine'
        ordering = ['user__first_name', 'user__last_name']
        get_latest_by = "last_modified"
Esempio n. 19
0
class TrustAnchorCertificate(models.Model):

    owner = models.ForeignKey(User)
    status = models.CharField(max_length=10,
                              default="incomplete",
                              choices=STATUS_CHOICES,
                              editable=False)
    sha256_digest = models.CharField(
        max_length=64,
        default="",
        blank=True,
    )
    sha1_fingerprint = models.CharField(
        max_length=64,
        default="",
        blank=True,
    )
    #editable=False)
    serial_number = models.CharField(
        max_length=64,
        default=-01,
        blank=True,
    )
    #editable=False)

    domain = models.CharField(
        max_length=512,
        default="",
        help_text=
        "We recommend using a top-level domain here (e.g. example.com)")
    common_name = models.CharField(
        max_length=512,
        default="",
        help_text="Always set this to the same value as domain")
    dns = models.CharField(
        verbose_name="DNS",
        max_length=512,
        default="",
        help_text=
        """We recommend using a top-level domain here (e.g. example.com).
                             This field should match the email field exactly.
                            """)
    email = models.CharField(
        max_length=512,
        default="",
        help_text=
        """We recommend using a top-level domain here (e.g. example.com).
                                This field should match the DNS field exactly."""
    )
    rsa_keysize = models.IntegerField(max_length=4,
                                      default=2048,
                                      choices=RSA_KEYSIZE_CHOICES)
    country = models.CharField(max_length=2, default="US")
    state = models.CharField(
        blank=True,
        max_length=2,
        choices=US_STATES,
    )
    city = models.CharField(
        max_length=64,
        help_text="No slashes. Letters, numbers, and dashes are okay. ")
    organization = models.CharField(
        max_length=64,
        help_text="No slashes. Letters, numbers, and dashes are okay. ")
    private_key_path = models.CharField(max_length=1024,
                                        default="",
                                        blank=True)
    public_key_path = models.CharField(max_length=1024, default="", blank=True)
    completed_dir_path = models.CharField(max_length=1024,
                                          default="",
                                          blank=True)

    private_expire_days = models.IntegerField(max_length=1024,
                                              default="1",
                                              blank=True)
    private_zip_name = models.CharField(max_length=1024,
                                        default="",
                                        blank=True)
    presigned_zip_url = models.CharField(max_length=1024,
                                         default="",
                                         blank=True)

    presigned_zip_s3 = models.CharField(max_length=1024,
                                        default="",
                                        blank=True)

    public_cert_pem_url = models.CharField(max_length=1024,
                                           default="",
                                           blank=True)
    public_cert_pem_s3 = models.CharField(max_length=1024,
                                          default="",
                                          blank=True)
    public_cert_der_url = models.CharField(max_length=1024,
                                           default="",
                                           blank=True)
    public_cert_der_s3 = models.CharField(max_length=1024,
                                          default="",
                                          blank=True)
    public_cert_status_url = models.CharField(max_length=1024,
                                              default="",
                                              blank=True)
    public_cert_status_sha1_url = models.CharField(max_length=1024,
                                                   default="",
                                                   blank=True)
    public_cert_x5c_url = models.CharField(max_length=1024,
                                           default="",
                                           blank=True)
    revoke = models.BooleanField(default=False)
    expired = models.BooleanField(default=False, editable=False)
    verified = models.BooleanField()
    verified_message_sent = models.BooleanField()
    rcsp_response = models.TextField(max_length=512, blank=True, default="")
    notes = models.TextField(max_length=1024, blank=True, default="")
    npi = models.CharField(max_length=20, default="", blank=True)
    contact_first_name = models.CharField(max_length=100, default="")
    contact_last_name = models.CharField(max_length=100, default="")
    contact_email = models.EmailField()
    contact_mobile_phone = PhoneNumberField(max_length=15, blank=True)
    contact_land_phone = PhoneNumberField(max_length=15, blank=True)
    contact_fax = PhoneNumberField(max_length=15, blank=True)
    expiration_date = models.DateField(blank=True, editable=False)
    expire_days = models.IntegerField(max_length=5,
                                      default=365,
                                      choices=EXPIRE_CHOICES)
    creation_date = models.DateField(auto_now_add=True)

    def __unicode__(self):
        return '%s (%s) Status=%s, Created %s.' % (
            self.domain, self.serial_number, self.status, self.creation_date)

    class Meta:
        get_latest_by = "creation_date"
        ordering = ('-creation_date', )

    def save(self, **kwargs):

        if not self.sha256_digest and self.revoke == False:
            """I'm a new certificate"""

            today = datetime.date.today()
            self.expiration_date = today + datetime.timedelta(
                days=self.expire_days)
            result = create_trust_anchor_certificate(
                common_name=self.common_name,
                email=self.email,
                dns=self.dns,
                expires=self.expire_days,
                organization=self.organization,
                city=self.city,
                state=self.state,
                country=self.country,
                rsakey=self.rsa_keysize,
                user=self.owner.username)

            self.sha256_digest = result['sha256_digest']
            self.serial_number = result['serial_number']
            self.sha1_fingerprint = result['sha1_fingerprint']
            self.notes = result['notes']
            self.private_zip_name = result['anchor_zip_download_file_name']
            self.status = result['status']
            self.private_key_path = result['private_key_path']
            self.public_key_path = result['public_key_path']
            self.completed_dir_path = result['completed_dir_path']

            #send the verifier an email notification
            msg = """
            <html>
            <head>
            </head>
            <body>
            A new Direct Trust Anchor was created by %s and requires your review.
            Here is a link for the domain %s:
            <ul>
            <li><a href="/admin/certificates/trustanchorcertificate/%s">%s</a></li>
            </ul>
            </body>
            </html>
            """ % (self.organization, self.domain, self.id, self.domain)
            if settings.SEND_CA_EMAIL:
                msg = EmailMessage(
                    '[DirectCA]A new Trust Anchor certificate requires verification',
                    msg, settings.EMAIL_HOST_USER, [
                        settings.CA_VERIFIER_EMAIL,
                    ])
                msg.content_subtype = "html"  # Main content is now text/html
                msg.send()

            # Create the CRL config file
            crl_result = create_crl_conf(
                common_name=self.common_name,
                email=self.email,
                dns=self.dns,
                anchor_dns=self.dns,
                expires=self.expire_days,
                organization=self.organization,
                city=self.city,
                state=self.state,
                country=self.country,
                rsakey=self.rsa_keysize,
                user=self.owner.username,
                public_key_path=result['public_key_path'],
                private_key_path=result['private_key_path'],
                completed_anchor_dir=result['completed_dir_path'])

            return super(TrustAnchorCertificate, self).save(**kwargs)




        if self.verified and not self.verified_message_sent and \
           self.status in  ('unverified', 'good'):
            """This is the verify routine"""

            self.status = "good"
            # Get the response
            rcsp_result = write_verification_message(
                self.serial_number,
                self.common_name,
                "good",
                self.sha1_fingerprint,
            )
            #Write it to db
            self.rcsp_response = rcsp_result
            fn = "%s.json" % (self.serial_number)
            #Write it to file
            fp = os.path.join(self.completed_dir_path, fn)

            f = open(fp, "w")
            f.write(str(rcsp_result))
            f.close()

            #Upload the RCSP file to S3
            if settings.USE_S3:
                s = SimpleS3()
                self.public_cert_status_url = s.store_in_s3(
                    fn, fp, bucket=settings.RCSP_BUCKET, public=True)
                self.public_cert_status_url = s.build_pretty_url(
                    self.public_cert_status_url, settings.RCSP_BUCKET)

            #"JOSE -------------------------------------------------------------"
            #get all the files
            certfilelist = [settings.CA_PUBLIC_CERT, self.public_key_path]

            fn = "%s-chain.pem" % (self.dns)
            chained_cert_path = os.path.join(self.completed_dir_path, fn)
            certlist = chain_keys_in_list(chained_cert_path, certfilelist)
            #write the json

            x5c_json = write_x5c_message(self.email, certlist)

            # set the filename ------------------------------------------------
            fn = "%s-x5c.json" % (self.serial_number)

            # Write it to file ------------------------------------------------
            fp = os.path.join(self.completed_dir_path, fn)

            f = open(fp, "w")
            f.write(str(x5c_json))
            f.close()

            #Upload the x5c file to S3
            s = SimpleS3()
            if settings.USE_S3:
                key = "x5c/" + fn
                self.public_cert_x5c_url = s.store_in_s3(
                    key, fp, bucket=settings.X5C_BUCKET, public=True)
                self.public_cert_x5c_url = s.build_pretty_url(
                    self.public_cert_x5c_url, settings.X5C_BUCKET)

            #Calculate the SHA1 fingerprint & write it to a file
            digestsha1 = json.dumps(sha.sha1_from_filepath(fp), indent=4)
            fn = "%s-sha1.json" % (self.serial_number)
            fp = os.path.join(self.completed_dir_path, fn)
            f = open(fp, "w")
            f.write(str(digestsha1))
            f.close()

            #Upload the RCSP SHA! Digest to S3
            if settings.USE_S3:
                self.public_cert_status_sha1_url = s.store_in_s3(
                    fn, fp, bucket=settings.RCSPSHA1_BUCKET, public=True)
                self.public_cert_status_sha1_url = s.build_pretty_url(
                    self.public_cert_status_sha1_url, settings.RCSPSHA1_BUCKET)

            #Upload the PEM and DER public certificates
            fn = "%s.pem" % (self.dns)
            key = "%s/%s/%s" % (self.owner.username, self.dns, fn)
            fp = os.path.join(self.completed_dir_path, fn)
            if settings.USE_S3:
                self.public_cert_pem_url = s.store_in_s3(
                    key, fp, bucket=settings.PUBCERT_BUCKET, public=True)
                self.public_cert_pem_url = s.build_pretty_url(
                    self.public_cert_pem_url, settings.PUBCERT_BUCKET)

                self.public_cert_pem_s3 = json.dumps({
                    "bucket": settings.PUBCERT_BUCKET,
                    "key": key
                })

            fn = "%s.der" % (self.dns)
            key = "%s/%s/%s" % (self.owner.username, self.dns, fn)
            fp = os.path.join(self.completed_dir_path, fn)
            if settings.USE_S3:
                self.public_cert_der_url = s.store_in_s3(
                    key, fp, bucket=settings.PUBCERT_BUCKET, public=True)
                self.public_cert_der_url = s.build_pretty_url(
                    self.public_cert_der_url, settings.PUBCERT_BUCKET)
                self.public_cert_der_s3 = json.dumps({
                    "bucket": settings.PUBCERT_BUCKET,
                    "key": key
                })

            #Send the zip file and expire in one week
            fn = self.private_zip_name
            fp = os.path.join(self.completed_dir_path, self.private_zip_name)
            key = "%s/%s/%s" % (self.owner.username, self.dns, fn)
            if settings.USE_S3:
                self.presigned_zip_url = s.store_in_s3(
                    key, fp, bucket=settings.PUBCERT_BUCKET, public=True)

                self.presigned_zip_url = s.build_pretty_url(
                    self.presigned_zip_url, settings.PUBCERT_BUCKET)

                #We dont need this for trust anchos since there is no private key give.
                #self.presigned_zip_url = s.get_presignedurl(key, bucket = settings.PRIVCERT_BUCKET)

                self.presigned_zip_s3 = json.dumps({
                    "bucket": settings.PUBCERT_BUCKET,
                    "key": key
                })
            """ Mark th certificate as verified """
            self.verified = True

            #send the verification email.
            msg = """
            <html>
            <head>
            </head>
            <body>
            Congratulations. Your trust anchor has for %s been verified.
            Here are some links to your public certificates and related status
            information.
            
            <ul>
            <li><a href="%s">PEM File                             - %s</a></li>
            <li><a href="%s">DER File                             - %s</a></li>
            <li><a href="%s">Status                               - %s</a></li>
            <li><a href="%s">Status SHA1 Digest                   - %s</a></li>
            <li><a href="%s">Certificate Chain in JOSE x5c Format - %s</a></li>
            </ul>
            </body>
            </html>
            """ % (self.domain, self.public_cert_pem_url,
                   self.public_cert_pem_url, self.public_cert_der_url,
                   self.public_cert_der_url, self.public_cert_status_url,
                   self.public_cert_status_url,
                   self.public_cert_status_sha1_url,
                   self.public_cert_status_sha1_url, self.public_cert_x5c_url,
                   self.public_cert_x5c_url)
            if settings.SEND_CA_EMAIL:
                msg = EmailMessage(
                    '[DirectCA]Your Trust Anchor Certificate has been verified',
                    msg, settings.EMAIL_HOST_USER,
                    [self.owner.email, self.contact_email])
                msg.content_subtype = "html"  # Main content is now text/html
                msg.send()

            self.verified_message_sent = True

        if self.revoke and self.status != "revoked":
            self.status = "revoked"

            # Build the  RCSP response
            # Get the status
            self.rcsp_response = write_verification_message(
                self.serial_number,
                self.common_name,
                "revoked",
                self.sha1_fingerprint,
            )
            fn = "%s.json" % (self.serial_number)

            #Write it to file
            fp = os.path.join(self.completed_dir_path, fn)

            f = open(fp, "w")
            f.write(str(self.rcsp_response))
            f.close()

            #Upload the RCSP file to S3
            if settings.USE_S3:
                s = SimpleS3()
                url = s.store_in_s3(fn,
                                    fp,
                                    bucket=settings.RCSP_BUCKET,
                                    public=True)

            #Calculate the SHA1 fingerprint & write it to a file
            digestsha1 = json.dumps(sha.sha1_from_filepath(fp), indent=4)
            fn = "%s-sha1.json" % (self.serial_number)
            fp = os.path.join(self.completed_dir_path, fn)
            f = open(fp, "w")
            f.write(str(digestsha1))
            f.close()
            if settings.USE_S3:
                #Upload the RCSP SHA! Digest to S3
                url = s.store_in_s3(fn,
                                    fp,
                                    bucket=settings.RCSPSHA1_BUCKET,
                                    public=True)

                #Delete all the old files:
                #PEM, DIR, ZIP
                if self.presigned_zip_s3:
                    s3info = json.loads(self.presigned_zip_s3)
                    self.presigned_zip_url = s.delete_in_s3(
                        s3info['bucket'],
                        s3info['key'],
                    )

                if self.public_cert_der_s3:
                    s3info = json.loads(self.public_cert_der_s3)
                    self.public_cert_der_url = s.delete_in_s3(
                        s3info['bucket'],
                        s3info['key'],
                    )

                if self.public_cert_pem_s3:
                    s3info = json.loads(self.public_cert_pem_s3)
                    self.public_cert_pem_url = s.delete_in_s3(
                        s3info['bucket'],
                        s3info['key'],
                    )

            #revoke the cert
            revoke(self)

        super(TrustAnchorCertificate, self).save(**kwargs)

    def delete(self, **kwargs):
        self.revoked = True
        self.status = "revoked"

        # Build the RCSP response
        rcsp_result = write_verification_message(
            self.serial_number,
            self.common_name,
            "revoked",
            self.sha1_fingerprint,
        )
        #Write it to db
        self.rcsp_response = rcsp_result
        fn = "%s.json" % (self.serial_number)
        #Write it to file
        fp = os.path.join(self.completed_dir_path, fn)

        f = open(fp, "w")
        f.write(str(rcsp_result))
        f.close()

        #Upload the RCSP file to S3
        s = SimpleS3()
        if settings.USE_S3:
            url = s.store_in_s3(fn,
                                fp,
                                bucket=settings.RCSP_BUCKET,
                                public=True)

        #Calculate the SHA1 fingerprint & write it to a file
        digestsha1 = json.dumps(sha.sha1_from_filepath(fp), indent=4)
        fn = "%s-sha1.json" % (self.serial_number)
        fp = os.path.join(self.completed_dir_path, fn)
        f = open(fp, "w")
        f.write(str(digestsha1))
        f.close()

        #Upload the RCSP SHA! Digest to S3
        if settings.USE_S3:
            url = s.store_in_s3(fn,
                                fp,
                                bucket=settings.RCSPSHA1_BUCKET,
                                public=True)

        #Revoke the cert.
        revoke(self)
        super(TrustAnchorCertificate, self).save(**kwargs)