class Conference(models.Model): """ the full conference for a specific year, e.g. US PyCon 2012. """ title = models.CharField(_("title"), max_length=100) # when the conference runs start_date = models.DateField(_("start date"), null=True, blank=True) end_date = models.DateField(_("end date"), null=True, blank=True) # timezone the conference is in timezone = TimeZoneField(_("timezone"), blank=True) def __unicode__(self): return self.title def save(self, *args, **kwargs): super(Conference, self).save(*args, **kwargs) if self.id in CONFERENCE_CACHE: del CONFERENCE_CACHE[self.id] def delete(self): pk = self.pk super(Conference, self).delete() try: del CONFERENCE_CACHE[pk] except KeyError: pass class Meta(object): verbose_name = _("conference") verbose_name_plural = _("conferences")
class Person(TendenciBaseModel): user = models.OneToOneField(User, related_name="profile", verbose_name=_('user')) phone = models.CharField(_('phone'), max_length=50, blank=True) address = models.CharField(_('address'), max_length=150, blank=True) address2 = models.CharField(_('address2'), max_length=100, default='', blank=True) member_number = models.CharField(_('member number'), max_length=50, blank=True) city = models.CharField(_('city'), max_length=50, blank=True) state = models.CharField(_('state'), max_length=50, blank=True) zipcode = models.CharField(_('zipcode'), max_length=50, blank=True) county = models.CharField(_('county'), max_length=50, blank=True) country = models.CharField(_('country'), max_length=50, blank=True) url = models.CharField(_('url'), max_length=100, blank=True) time_zone = TimeZoneField(_('timezone')) language = models.CharField(_('language'), max_length=10, choices=settings.LANGUAGES, default=settings.LANGUAGE_CODE) perms = generic.GenericRelation(ObjectPermission, object_id_field="object_id", content_type_field="content_type") class Meta: abstract = True
class Profile(ModelBase): """Profile model for django users, get it with user.get_profile().""" user = models.OneToOneField(User, primary_key=True, verbose_name=_lazy(u'User')) name = models.CharField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'Display name')) public_email = models.BooleanField( # show/hide email default=False, verbose_name=_lazy(u'Make my email public')) avatar = models.ImageField(upload_to=settings.USER_AVATAR_PATH, null=True, blank=True, verbose_name=_lazy(u'Avatar'), max_length=settings.MAX_FILEPATH_LENGTH) bio = models.TextField(null=True, blank=True, verbose_name=_lazy(u'Biography')) website = models.URLField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'Website')) twitter = models.URLField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'Twitter URL')) facebook = models.URLField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'Facebook URL')) irc_handle = models.CharField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'IRC nickname')) timezone = TimeZoneField(null=True, blank=True, verbose_name=_lazy(u'Timezone')) country = models.CharField(max_length=2, choices=COUNTRIES, null=True, blank=True, verbose_name=_lazy(u'Country')) # No city validation city = models.CharField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'City')) livechat_id = models.CharField(default=None, null=True, blank=True, max_length=255, verbose_name=_lazy(u'Livechat ID')) def __unicode__(self): return unicode(self.user)
class Server(models.Model): """Guild Wars 2 Server""" class Meta: ordering = ['name'] name = models.CharField(max_length=50) tz = TimeZoneField('server time zone') def __unicode__(self): return self.name
class Account(models.Model): user = models.ForeignKey(User, unique=True, verbose_name=_("user")) timezone = TimeZoneField(_("timezone")) language = models.CharField(_("language"), max_length=10, choices=settings.LANGUAGES, default=settings.LANGUAGE_CODE) def __unicode__(self): return self.user.username
class Profile(ModelBase): """Profile model for django users, get it with user.get_profile().""" user = models.OneToOneField(User, primary_key=True, verbose_name=_lazy(u'User')) name = models.CharField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'Display name')) public_email = models.BooleanField( # show/hide email default=False, verbose_name=_lazy(u'Make my email public')) avatar = models.ImageField(upload_to=settings.USER_AVATAR_PATH, null=True, blank=True, verbose_name=_lazy(u'Avatar'), max_length=settings.MAX_FILEPATH_LENGTH) bio = models.TextField(null=True, blank=True, verbose_name=_lazy(u'Biography')) website = models.URLField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'Website')) twitter = models.URLField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'Twitter URL')) facebook = models.URLField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'Facebook URL')) irc_handle = models.CharField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'IRC nickname')) timezone = TimeZoneField(null=True, blank=True, verbose_name=_lazy(u'Timezone')) country = models.CharField(max_length=2, choices=COUNTRIES, null=True, blank=True, verbose_name=_lazy(u'Country')) # No city validation city = models.CharField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'City')) locale = LocaleField(default=settings.LANGUAGE_CODE, verbose_name=_lazy(u'Preferred language')) class Meta(object): permissions = (('view_karma_points', 'Can view karma points'), ('deactivate_users', 'Can deactivate users'),) def __unicode__(self): return unicode(self.user) def get_absolute_url(self): return reverse('users.profile', args=[self.user_id]) def clear(self): """Clears out the users profile""" self.name = '' self.public_email = False self.avatar = None self.bio = '' self.website = '' self.twitter = '' self.facebook = '' self.irc_handle = '' self.city = ''
class Setting(models.Model): """ Settings model for specific blog settings """ blog_title = models.CharField(max_length=75, null=True, blank=True) blog_tagline = models.CharField(max_length=150, null=True, blank=True) name = models.CharField(max_length=30, null=True, blank=True) bio = models.TextField(null=True, blank=True) disqus_shortname = models.CharField(max_length=75, null=True, blank=True) user = models.ForeignKey(User, editable=False) timezone = TimeZoneField(default="US/Central") objects = SettingManager()
class Contact(TendenciBaseModel): """ Contact records are created when someone fills out a form. The form creates the contact with a message. Later the contact can be updated to include comments for further communication. """ guid = models.CharField(max_length=40) timezone = TimeZoneField() user = models.ForeignKey(User, null=True, related_name='contact_user') first_name = models.CharField(max_length=100, blank=True) middle_name = models.CharField(max_length=100, blank=True) last_name = models.CharField(max_length=100, blank=True) suffix = models.CharField(max_length=5, blank=True) addresses = models.ManyToManyField(Address, blank=True) phones = models.ManyToManyField(Phone, blank=True) emails = models.ManyToManyField(Email, blank=True) urls = models.ManyToManyField(URL, blank=True) companies = models.ManyToManyField(Company, blank=True) message = models.TextField() perms = GenericRelation(ObjectPermission, object_id_field="object_id", content_type_field="content_type") # TODO: consider attachments objects = ContactManager() class Meta: permissions = (("view_contact", _("Can view contact")), ) app_label = 'contacts' @models.permalink def get_absolute_url(self): return ("contact", [self.pk]) def save(self, *args, **kwargs): if not self.id: self.guid = str(uuid.uuid1()) super(Contact, self).save(*args, **kwargs) def __unicode__(self): if self.first_name: return '%s %s' % (self.first_name, self.last_name) else: return '%s' % self.user
class Conference(models.Model): """ the full conference for a specific year, e.g. US PyCon 2012. """ title = models.CharField(_("title"), max_length=100) slug = models.SlugField(_("slug"), null=True, blank=True) # when the conference runs start_date = models.DateField(_("start date"), null=True, blank=True) end_date = models.DateField(_("end date"), null=True, blank=True) # timezone the conference is in timezone = TimeZoneField(_("timezone"), blank=True) reviews_start_date = models.DateTimeField(null=True, blank=True) reviews_end_date = models.DateTimeField(null=True, blank=True) reviews_active = models.NullBooleanField() tickets_editable = models.BooleanField(default=True) tickets_editable_until = models.DateTimeField(null=True, blank=True) anonymize_proposal_author = models.BooleanField( _("anonymize proposal author"), default=True) def __unicode__(self): return self.title def save(self, *args, **kwargs): super(Conference, self).save(*args, **kwargs) if self.id in CONFERENCE_CACHE: del CONFERENCE_CACHE[self.id] def delete(self): pk = self.pk super(Conference, self).delete() try: del CONFERENCE_CACHE[pk] except KeyError: pass def get_reviews_active(self): if self.reviews_active is not None: return self.reviews_active if self.reviews_start_date and self.reviews_end_date: return self.reviews_start_date <= now() <= self.reviews_end_date return False class Meta(object): verbose_name = _("conference") verbose_name_plural = _("conferences")
class Person(TendenciBaseModel): user = UnsavedOneToOne(User, related_name="profile", verbose_name=_('user')) phone = models.CharField(_('phone'), max_length=50, blank=True) address = models.CharField(_('address'), max_length=150, blank=True) address2 = models.CharField(_('address2'), max_length=100, default='', blank=True) member_number = models.CharField(_('member number'), max_length=50, blank=True) city = models.CharField(_('city'), max_length=50, blank=True) state = models.CharField(_('state'), max_length=50, blank=True) zipcode = models.CharField(_('zipcode'), max_length=50, blank=True) county = models.CharField(_('county'), max_length=50, blank=True) country = models.CharField(_('country'), max_length=255, blank=True) # fields to be used for the alternate address address_2 = models.CharField(_('address'), max_length=150, blank=True) address2_2 = models.CharField(_('address2'), max_length=100, default='', blank=True) member_number_2 = models.CharField(_('member number'), max_length=50, blank=True) city_2 = models.CharField(_('city'), max_length=50, blank=True) state_2 = models.CharField(_('state'), max_length=50, blank=True) zipcode_2 = models.CharField(_('zipcode'), max_length=50, blank=True) county_2 = models.CharField(_('county'), max_length=50, blank=True) country_2 = models.CharField(_('country'), max_length=255, blank=True) url = models.CharField(_('url'), max_length=100, blank=True) time_zone = TimeZoneField(_('timezone')) language = models.CharField(_('language'), max_length=10, choices=settings.LANGUAGES, default=settings.LANGUAGE_CODE) perms = GenericRelation(ObjectPermission, object_id_field="object_id", content_type_field="content_type") class Meta: abstract = True def get_address(self): """ Returns full address depending on which attributes are available. """ state_zip = ' '.join([s for s in (self.state, self.zipcode) if s]) city_state_zip = ', '.join([s for s in (self.city, state_zip, self.country) if s]) return '%s %s %s' % (self.address, self.address2, city_state_zip) def get_alternate_address(self): """ Returns full alternate address depending on which attributes are available. """ state_zip = ' '.join([s for s in (self.state_2, self.zipcode_2) if s]) city_state_zip = ', '.join([s for s in (self.city_2, state_zip, self.country_2) if s]) return '%s %s %s' % (self.address_2, self.address2_2, city_state_zip)
class Profile(models.Model): user = models.OneToOneField(User) skype = models.CharField("Skype ID", max_length=20, null=True, blank=True) aim = models.CharField("AIM", max_length=20, null=True, blank=True) gchat = models.CharField("Google Chat", max_length=20, null=True, blank=True) phone = models.CharField("Phone number", max_length=20, null=True, blank=True) is_available = models.BooleanField("Available now") timezone = TimeZoneField(choices=sorted( PRETTY_TIMEZONE_CHOICES, key=lambda x: (int(x[1][4:9]), x[1]))) skills = models.ManyToManyField('Skill', blank=True) def __unicode__(self): return unicode(self.user)
class UserProfile(ModelBase): """ The UserProfile *must* exist for each django.contrib.auth.models.User object. This may be relaxed once Dekiwiki isn't the definitive db for user info. timezone and language fields are syndicated to Dekiwiki """ # Website fields defined for the profile form # TODO: Someday this will probably need to allow arbitrary per-profile # entries, and these will just be suggestions. website_choices = [('website', dict( label=_(u'Website'), prefix='http://', regex='^https?://', fa_icon='icon-link', )), ('twitter', dict( label=_(u'Twitter'), prefix='https://twitter.com/', regex='^https?://twitter.com/', fa_icon='icon-twitter', )), ('github', dict( label=_(u'GitHub'), prefix='https://github.com/', regex='^https?://github.com/', fa_icon='icon-github', )), ('stackoverflow', dict( label=_(u'Stack Overflow'), prefix='https://stackoverflow.com/users/', regex='^https?://stackoverflow.com/users/', fa_icon='icon-stackexchange', )), ('linkedin', dict( label=_(u'LinkedIn'), prefix='https://www.linkedin.com/', regex='^https?:\/\/www.linkedin.com\/(in|pub)', fa_icon='icon-linkedin', )), ('mozillians', dict( label=_(u'Mozillians'), prefix='https://mozillians.org/u/', regex='^https?://mozillians.org/u/', fa_icon='icon-group', )), ('facebook', dict( label=_(u'Facebook'), prefix='https://www.facebook.com/', regex='^https?://www.facebook.com/', fa_icon='icon-facebook', ))] # This could be a ForeignKey, except wikidb might be # a different db deki_user_id = models.PositiveIntegerField(default=0, editable=False) timezone = TimeZoneField(null=True, blank=True, verbose_name=_(u'Timezone')) locale = LocaleField(null=True, blank=True, db_index=True, verbose_name=_(u'Language')) homepage = models.URLField(max_length=255, blank=True, default='', error_messages={ 'invalid': _(u'This URL has an invalid format. ' u'Valid URLs look like ' u'http://example.com/my_page.') }) title = models.CharField(_(u'Title'), max_length=255, default='', blank=True) fullname = models.CharField(_(u'Name'), max_length=255, default='', blank=True) organization = models.CharField(_(u'Organization'), max_length=255, default='', blank=True) location = models.CharField(_(u'Location'), max_length=255, default='', blank=True) bio = models.TextField(_(u'About Me'), blank=True) irc_nickname = models.CharField(_(u'IRC nickname'), max_length=255, default='', blank=True) tags = NamespacedTaggableManager(_(u'Tags'), blank=True) # should this user receive contentflagging emails? content_flagging_email = models.BooleanField(default=False) user = models.ForeignKey(User, null=True, editable=False, blank=True) # HACK: Grab-bag field for future expansion in profiles # We can store arbitrary data in here and later migrate to relational # tables if the data ever needs to be indexed & queried. Otherwise, # this keeps things nicely denormalized. Ideally, access to this field # should be gated through accessors on the model to make that transition # easier. misc = JSONField(blank=True, null=True) class Meta: db_table = 'user_profiles' def __unicode__(self): return '%s: %s' % (self.id, self.deki_user_id) def get_absolute_url(self): return self.user.get_absolute_url() @property def websites(self): if 'websites' not in self.misc: self.misc['websites'] = {} return self.misc['websites'] @websites.setter def websites(self, value): self.misc['websites'] = value @cached_property def beta_tester(self): return (constance.config.BETA_GROUP_NAME in self.user.groups.values_list('name', flat=True)) @property def is_banned(self): return self.user.bans.filter(is_active=True).exists() def active_ban(self): if self.is_banned: return self.user.bans.filter(is_active=True)[:1][0] def gravatar(self): return gravatar_url(self.user) def allows_editing_by(self, user): if user == self.user: return True if user.is_staff or user.is_superuser: return True return False def wiki_activity(self): return (Revision.objects.filter( creator=self.user).order_by('-created')[:5])
class News(TendenciBaseModel): guid = models.CharField(max_length=40) slug = SlugField(_('URL Path'), unique=True) timezone = TimeZoneField(_('Time Zone')) headline = models.CharField(max_length=200, blank=True) summary = models.TextField(blank=True) body = tinymce_models.HTMLField() source = models.CharField(max_length=300, blank=True) first_name = models.CharField(_('First Name'), max_length=100, blank=True) last_name = models.CharField(_('Last Name'), max_length=100, blank=True) phone = models.CharField(max_length=50, blank=True) fax = models.CharField(max_length=50, blank=True) email = models.CharField(max_length=120, blank=True) website = models.CharField(max_length=300, blank=True) thumbnail = models.ForeignKey( 'NewsImage', default=None, null=True, help_text= _('The thumbnail image can be used on your homepage or sidebar if it is setup in your theme. The thumbnail image will not display on the news page.' )) release_dt = models.DateTimeField(_('Release Date/Time'), null=True, blank=True) syndicate = models.BooleanField(_('Include in RSS feed'), default=True) design_notes = models.TextField(_('Design Notes'), blank=True) group = models.ForeignKey(Group, null=True, default=get_default_group, on_delete=models.SET_NULL) tags = TagField(blank=True) #for podcast feeds enclosure_url = models.CharField(_('Enclosure URL'), max_length=500, blank=True) # for podcast feeds enclosure_type = models.CharField(_('Enclosure Type'), max_length=120, blank=True) # for podcast feeds enclosure_length = models.IntegerField(_('Enclosure Length'), default=0) # for podcast feeds use_auto_timestamp = models.BooleanField(_('Auto Timestamp')) # html-meta tags meta = models.OneToOneField(MetaTags, null=True) categories = generic.GenericRelation(CategoryItem, object_id_field="object_id", content_type_field="content_type") perms = generic.GenericRelation(ObjectPermission, object_id_field="object_id", content_type_field="content_type") objects = NewsManager() class Meta: permissions = (("view_news", "Can view news"), ) verbose_name_plural = "News" def get_meta(self, name): """ This method is standard across all models that are related to the Meta model. Used to generate dynamic meta information niche to this model. """ return NewsMeta().get_meta(self, name) @models.permalink def get_absolute_url(self): return ("news.detail", [self.slug]) def __unicode__(self): return self.headline def save(self, *args, **kwargs): if not self.id: self.guid = str(uuid.uuid1()) photo_upload = kwargs.pop('photo', None) super(News, self).save(*args, **kwargs) if photo_upload and self.pk: image = NewsImage(object_id=self.pk, creator=self.creator, creator_username=self.creator_username, owner=self.owner, owner_username=self.owner_username) photo_upload.file.seek(0) image.file.save(photo_upload.name, photo_upload) # save file row image.save() # save image row if self.thumbnail: self.thumbnail.delete() # delete image and file row self.thumbnail = image # set image self.save() if self.thumbnail: if self.is_public(): set_s3_file_permission(self.thumbnail.file, public=True) else: set_s3_file_permission(self.thumbnail.file, public=False) @property def category_set(self): items = {} for cat in self.categories.select_related('category__name', 'parent__name'): if cat.category: items["category"] = cat.category elif cat.parent: items["sub_category"] = cat.parent return items def is_public(self): return all([ self.allow_anonymous_view, self.status, self.status_detail in ['active'] ])
class Profile(ModelBase, SearchMixin): """Profile model for django users, get it with user.get_profile().""" user = models.OneToOneField(User, primary_key=True, verbose_name=_lazy(u'User')) name = models.CharField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'Display name')) public_email = models.BooleanField( # show/hide email default=False, verbose_name=_lazy(u'Make my email public')) avatar = models.ImageField(upload_to=settings.USER_AVATAR_PATH, null=True, blank=True, verbose_name=_lazy(u'Avatar'), max_length=settings.MAX_FILEPATH_LENGTH) bio = models.TextField(null=True, blank=True, verbose_name=_lazy(u'Biography')) website = models.URLField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'Website')) twitter = models.URLField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'Twitter URL')) facebook = models.URLField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'Facebook URL')) irc_handle = models.CharField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'IRC nickname')) timezone = TimeZoneField(null=True, blank=True, verbose_name=_lazy(u'Timezone')) country = models.CharField(max_length=2, choices=COUNTRIES, null=True, blank=True, verbose_name=_lazy(u'Country')) # No city validation city = models.CharField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'City')) locale = LocaleField(default=settings.LANGUAGE_CODE, verbose_name=_lazy(u'Preferred language')) class Meta(object): permissions = ( ('view_karma_points', 'Can view karma points'), ('deactivate_users', 'Can deactivate users'), ) def __unicode__(self): try: return unicode(self.user) except Exception as exc: return unicode('%d (%r)' % (self.pk, exc)) def get_absolute_url(self): return reverse('users.profile', args=[self.user_id]) def clear(self): """Clears out the users profile""" self.name = '' self.public_email = False self.avatar = None self.bio = '' self.website = '' self.twitter = '' self.facebook = '' self.irc_handle = '' self.city = '' @property def display_name(self): return self.name if self.name else self.user.username @property def twitter_usernames(self): from kitsune.customercare.models import Reply return list( Reply.objects.filter(user=self.user).values_list( 'twitter_username', flat=True).distinct()) @classmethod def get_mapping_type(cls): return UserMappingType @property def last_contribution_date(self): """Get the date of the user's last contribution.""" from kitsune.customercare.models import Reply from kitsune.questions.models import Answer from kitsune.wiki.models import Revision dates = [] # Latest Army of Awesome reply: try: aoa_reply = Reply.objects.filter(user=self.user).latest('created') dates.append(aoa_reply.created) except Reply.DoesNotExist: pass # Latest Support Forum answer: try: answer = Answer.objects.filter(creator=self.user).latest('created') dates.append(answer.created) except Answer.DoesNotExist: pass # Latest KB Revision edited: try: revision = Revision.objects.filter( creator=self.user).latest('created') dates.append(revision.created) except Revision.DoesNotExist: pass # Latest KB Revision reviewed: try: revision = Revision.objects.filter( reviewer=self.user).latest('reviewed') # Old revisions don't have the reviewed date. dates.append(revision.reviewed or revision.created) except Revision.DoesNotExist: pass if len(dates) == 0: return None return max(dates)
class Profile(models.Model): """User profile""" json_fields = [ ('user', 'user__json'), 'rate', 'rate_count', ] user = models.ForeignKey(User, unique=True, verbose_name=_('User')) city = models.ForeignKey(City, blank=True, null=True, verbose_name=_('City')) icq = models.CharField(max_length=10, blank=True, null=True, verbose_name=_('Icq')) jabber = models.EmailField(max_length=60, blank=True, null=True, verbose_name=_('Jabber')) site = models.URLField(blank=True, null=True, verbose_name=_('Web site')) rate = models.IntegerField(default=0, verbose_name=_('Personal rate')) rate_count = models.IntegerField(default=0, verbose_name=_('Count of raters')) posts_rate = models.IntegerField(default=0, verbose_name=_('Rate earned by posts')) comments_rate = models.IntegerField( default=0, verbose_name=_('Rate earned by comments')) blogs_rate = models.IntegerField(default=0, verbose_name=_('Rate earned by blogs')) timezone = TimeZoneField(default=TIME_ZONE, verbose_name=_('Timezone')) avatar = models.ImageField(upload_to=file_upload_path, blank=True, null=True, verbose_name=_('User picture')) hide_mail = models.BooleanField(default=True, verbose_name=_('Show email?')) reply_post = models.BooleanField( default=True, verbose_name=_('Send notify about reply to post?')) reply_comment = models.BooleanField( default=True, verbose_name=_('Send notify about reply to comment?')) reply_pm = models.BooleanField(default=True, verbose_name=_('Send notify about PM?')) reply_mention = models.BooleanField( default=True, verbose_name=_('Send notify about mention?')) reply_spy = models.BooleanField(default=True, verbose_name=_('Send notify about spy?')) about = models.TextField(blank=True, null=True, verbose_name=_('About')) other = models.TextField(blank=True, null=True, verbose_name=_('Field for addition')) def get_posts(self): """Get posts by user""" return Post.objects.filter(author=self.user) def get_city(self): """Get user city""" if self.city: return self.city.name else: return False def get_friends(self, friend_with_me=False): """Get user friends""" if friend_with_me: return Friends.objects.select_related('user').filter( friend=self.user) return Friends.objects.select_related('friend').filter(user=self) def get_blogs(self): """Get blogs contain it""" return UserInBlog.objects.select_related('blog').filter(user=self.user) def rate_user(self, user, value): """Rate user Keyword arguments: user -- User value -- Integer Returns: Integer """ if not UserRate.objects.filter(user=self).count(): self.rate += value self.rate_count += 1 rate = UserRate.objects.create(profile=self, user=user, negative=(value == -1)) return True else: return False def get_rate(self): """Get user rate""" return (self.rate + self.posts_rate * POST_RATE_COEFFICIENT + self.blogs_rate * BLOG_RATE_COEFFICIENT + self.comments_rate * COMMENT_RATE_COEFFICIENT) def check_access(self, type): """Check user access Keyword arguments: type -- Access: Returns: Boolean """ rate = self.get_rate() if type == Access.new_blog and rate >= NEWBLOG_RATE: return True elif type == Access.new_comment and rate >= NEWCOMMENT_RATE: return True elif type == Access.new_post and rate >= NEWPOST_RATE: return True elif type == Access.rate_comment and rate >= RATECOM_RATE: return True elif type == Access.rate_blog and rate >= RATEBLOG_RATE: return True elif type == Access.rate_post and rate >= RATEPOST_RATE: return True elif type == Access.rate_user and rate >= RATEUSER_RATE: return True else: return False def post_count(self): """Return post count""" return int(Post.objects.filter(author=self.user).count() or 0) def comment_count(self): """Return comment count""" return int(Comment.objects.filter(author=self.user).count()) def get_avatar(self): """Get url of user avatar""" try: return self.avatar.url except ValueError: return DEFAULT_AVATAR def get_me_on(self): """Return array of sites, where user is registered""" try: return self._getmeon except: pass try: class num: val = -1 def inc(self): self.val += 1 return True num = num() meon = MeOn.objects.filter(user=self.user) statused = Statused.objects.filter(user=self.user).all() for site in statused: meon = meon.exclude(url=site.url) action = lambda site: num.inc() and { 'url': site.url, 'title': site.title, 'statused': False, 'show': False, 'num': num.val } action_statused = lambda site: site.get_status() and num.inc( ) and { 'url': site.url, 'title': site.title, 'statused': True, 'show': site.show, 'num': num.val } self._getmeon = ([action(site) for site in meon] + [action_statused(site) for site in statused]) return self._getmeon except MeOn.DoesNotExist: return False def get_status(self): """Get array of user statuses from other sites""" try: return self._status except: self._status = [{ 'obj': service, 'text': service.get_status() } for service in Statused.objects.filter(user=self.user, show=True) ] return self._status def is_my_friend(self, user): """Check friends Keyword arguments: user -- User Returns: Integer """ if user.is_authenticated(): try: Friends.objects.get(user=user, friend=self.user) is_my_friend = 1 except Friends.DoesNotExist: is_my_friend = 0 else: is_my_friend = -1 return is_my_friend def update_last_visit(self): """Update last site visit time""" try: view = LastVisit.objects.get(user=self.user) view.date = datetime.datetime.now() view.save() except LastVisit.DoesNotExist: view = LastVisit(user=self.user) view.save() def is_online(self): """Check online status""" try: LastVisit.objects.get(user=self.user, date__gt=datetime.datetime.now() - datetime.timedelta(seconds=ONLINE_TIME)) return True except LastVisit.DoesNotExist: return False def get_block(self): """Get bans and blocks""" try: block = Blocks.objects.get(who=self.user) if block.check(): return block else: return None except Blocks.DoesNotExist: return None def get_rates(self): return UserRate.objects.select_related('user').filter(profile=self) def __unicode__(self): """Return username""" return self.user.username @property def user__json(self): return to_json(self.user) class Meta: verbose_name = _("User profile") verbose_name_plural = _("User profiles")
class Profile(ModelBase, SearchMixin): """Profile model for django users.""" user = models.OneToOneField(User, primary_key=True, verbose_name=_lazy(u'User')) name = models.CharField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'Display name')) public_email = models.BooleanField( # show/hide email default=False, verbose_name=_lazy(u'Make my email public')) avatar = models.ImageField(upload_to=settings.USER_AVATAR_PATH, null=True, blank=True, verbose_name=_lazy(u'Avatar'), max_length=settings.MAX_FILEPATH_LENGTH) bio = models.TextField(null=True, blank=True, verbose_name=_lazy(u'Biography')) website = models.URLField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'Website')) twitter = models.CharField(max_length=15, null=True, blank=True, validators=[TwitterValidator], verbose_name=_lazy(u'Twitter Username')) facebook = models.URLField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'Facebook URL')) mozillians = models.CharField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'Mozillians Username')) irc_handle = models.CharField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'IRC nickname')) timezone = TimeZoneField(null=True, blank=True, verbose_name=_lazy(u'Timezone')) country = models.CharField(max_length=2, choices=COUNTRIES, null=True, blank=True, verbose_name=_lazy(u'Country')) # No city validation city = models.CharField(max_length=255, null=True, blank=True, verbose_name=_lazy(u'City')) locale = LocaleField(default=settings.LANGUAGE_CODE, verbose_name=_lazy(u'Preferred language')) first_answer_email_sent = models.BooleanField( default=False, help_text=_lazy(u'Has been sent a first answer contribution email.')) first_l10n_email_sent = models.BooleanField( default=False, help_text=_lazy(u'Has been sent a first revision contribution email.')) involved_from = models.DateField(null=True, blank=True, verbose_name=_lazy(u'Involved with Mozilla from')) csat_email_sent = models.DateField(null=True, blank=True, verbose_name=_lazy(u'When the user was sent a community ' u'health survey')) class Meta(object): permissions = (('view_karma_points', 'Can view karma points'), ('deactivate_users', 'Can deactivate users'), ('screen_share', 'Can screen share'),) def __unicode__(self): try: return unicode(self.user) except Exception as exc: return unicode('%d (%r)' % (self.pk, exc)) def get_absolute_url(self): return reverse('users.profile', args=[self.user_id]) def clear(self): """Clears out the users profile""" self.name = '' self.public_email = False self.avatar = None self.bio = '' self.website = '' self.twitter = '' self.facebook = '' self.mozillians = '' self.irc_handle = '' self.city = '' @property def display_name(self): return self.name if self.name else self.user.username @property def twitter_usernames(self): from kitsune.customercare.models import Reply return list( Reply.objects.filter(user=self.user) .values_list('twitter_username', flat=True) .distinct()) @classmethod def get_mapping_type(cls): return UserMappingType @classmethod def get_serializer(cls, serializer_type='full'): # Avoid circular import from kitsune.users import api if serializer_type == 'full': return api.ProfileSerializer elif serializer_type == 'fk': return api.ProfileFKSerializer else: raise ValueError('Unknown serializer type "{}".'.format(serializer_type)) @property def last_contribution_date(self): """Get the date of the user's last contribution.""" from kitsune.customercare.models import Reply from kitsune.questions.models import Answer from kitsune.wiki.models import Revision dates = [] # Latest Army of Awesome reply: try: aoa_reply = Reply.objects.filter( user=self.user).latest('created') dates.append(aoa_reply.created) except Reply.DoesNotExist: pass # Latest Support Forum answer: try: answer = Answer.objects.filter( creator=self.user).latest('created') dates.append(answer.created) except Answer.DoesNotExist: pass # Latest KB Revision edited: try: revision = Revision.objects.filter( creator=self.user).latest('created') dates.append(revision.created) except Revision.DoesNotExist: pass # Latest KB Revision reviewed: try: revision = Revision.objects.filter( reviewer=self.user).latest('reviewed') # Old revisions don't have the reviewed date. dates.append(revision.reviewed or revision.created) except Revision.DoesNotExist: pass if len(dates) == 0: return None return max(dates) @property def settings(self): return self.user.settings @property def answer_helpfulness(self): # Avoid circular import from kitsune.questions.models import AnswerVote return AnswerVote.objects.filter(answer__creator=self.user, helpful=True).count()
class Article(TendenciBaseModel): CONTRIBUTOR_AUTHOR = 1 CONTRIBUTOR_PUBLISHER = 2 CONTRIBUTOR_CHOICES = ((CONTRIBUTOR_AUTHOR, _('Author')), (CONTRIBUTOR_PUBLISHER, _('Publisher'))) guid = models.CharField(max_length=40) slug = SlugField(_('URL Path'), unique=True) timezone = TimeZoneField(_('Time Zone')) headline = models.CharField(max_length=200, blank=True) summary = models.TextField(blank=True) body = tinymce_models.HTMLField() source = models.CharField(max_length=300, blank=True) first_name = models.CharField(_('First Name'), max_length=100, blank=True) last_name = models.CharField(_('Last Name'), max_length=100, blank=True) contributor_type = models.IntegerField(choices=CONTRIBUTOR_CHOICES, default=CONTRIBUTOR_AUTHOR) google_profile = models.URLField(_('Google+ URL'), blank=True) phone = models.CharField(max_length=50, blank=True) fax = models.CharField(max_length=50, blank=True) email = models.CharField(max_length=120, blank=True) website = models.CharField(max_length=300, blank=True) release_dt = models.DateTimeField(_('Release Date/Time'), null=True, blank=True) # used for better performance when retrieving a list of released articles release_dt_local = models.DateTimeField(null=True, blank=True) syndicate = models.BooleanField(_('Include in RSS feed'), default=True) featured = models.BooleanField(default=False) design_notes = models.TextField(_('Design Notes'), blank=True) group = models.ForeignKey(Group, null=True, default=get_default_group, on_delete=models.SET_NULL) tags = TagField(blank=True) # for podcast feeds enclosure_url = models.CharField(_('Enclosure URL'), max_length=500, blank=True) enclosure_type = models.CharField(_('Enclosure Type'), max_length=120, blank=True) enclosure_length = models.IntegerField(_('Enclosure Length'), default=0) not_official_content = models.BooleanField(_('Official Content'), blank=True, default=True) # html-meta tags meta = models.OneToOneField(MetaTags, null=True) categories = GenericRelation(CategoryItem, object_id_field="object_id", content_type_field="content_type") perms = GenericRelation(ObjectPermission, object_id_field="object_id", content_type_field="content_type") objects = ArticleManager() class Meta: permissions = (("view_article", _("Can view article")), ) verbose_name = _("Article") verbose_name_plural = _("Articles") app_label = 'articles' def get_meta(self, name): """ This method is standard across all models that are related to the Meta model. Used to generate dynamic methods coupled to this instance. """ return ArticleMeta().get_meta(self, name) @models.permalink def get_absolute_url(self): return ("article", [self.slug]) @models.permalink def get_version_url(self, hash): return ("article.version", [hash]) def __unicode__(self): return self.headline def save(self, *args, **kwargs): if not self.id: self.guid = str(uuid.uuid1()) self.assign_release_dt_local() super(Article, self).save(*args, **kwargs) def assign_release_dt_local(self): """ convert release_dt to the corresponding local time example: if release_dt: 2014-05-09 03:30:00 timezone: US/Pacific settings.TIME_ZONE: US/Central then the corresponding release_dt_local will be: 2014-05-09 05:30:00 """ now = datetime.now() now_with_tz = adjust_datetime_to_timezone(now, settings.TIME_ZONE) if self.timezone and self.release_dt and self.timezone.zone != settings.TIME_ZONE: time_diff = adjust_datetime_to_timezone( now, self.timezone) - now_with_tz self.release_dt_local = self.release_dt + time_diff else: self.release_dt_local = self.release_dt def age(self): return datetime.now() - self.create_dt @property def category_set(self): items = {} for cat in self.categories.select_related('category__name', 'parent__name'): if cat.category: items["category"] = cat.category elif cat.parent: items["sub_category"] = cat.parent return items @property def has_google_author(self): return self.contributor_type == self.CONTRIBUTOR_AUTHOR @property def has_google_publisher(self): return self.contributor_type == self.CONTRIBUTOR_PUBLISHER
class News(TendenciBaseModel): CONTRIBUTOR_AUTHOR = 1 CONTRIBUTOR_PUBLISHER = 2 CONTRIBUTOR_CHOICES = ((CONTRIBUTOR_AUTHOR, _('Author')), (CONTRIBUTOR_PUBLISHER, _('Publisher'))) guid = models.CharField(max_length=40) slug = SlugField(_('URL Path'), unique=True) timezone = TimeZoneField(_('Time Zone')) headline = models.CharField(max_length=200, blank=True) summary = models.TextField(blank=True) body = tinymce_models.HTMLField() source = models.CharField(max_length=300, blank=True) first_name = models.CharField(_('First Name'), max_length=100, blank=True) last_name = models.CharField(_('Last Name'), max_length=100, blank=True) contributor_type = models.IntegerField(choices=CONTRIBUTOR_CHOICES, default=CONTRIBUTOR_AUTHOR) google_profile = models.URLField(_('Google+ URL'), blank=True) phone = models.CharField(max_length=50, blank=True) fax = models.CharField(max_length=50, blank=True) email = models.CharField(max_length=120, blank=True) website = models.CharField(max_length=300, blank=True) thumbnail = models.ForeignKey( 'NewsImage', default=None, null=True, help_text= _('The thumbnail image can be used on your homepage or sidebar if it is setup in your theme. The thumbnail image will not display on the news page.' )) release_dt = models.DateTimeField(_('Release Date/Time'), null=True, blank=True) # used for better performance when retrieving a list of released news release_dt_local = models.DateTimeField(null=True, blank=True) syndicate = models.BooleanField(_('Include in RSS feed'), default=True) design_notes = models.TextField(_('Design Notes'), blank=True) groups = models.ManyToManyField(Group, default=get_default_group, related_name='group_news') tags = TagField(blank=True) uploaded_wechat_mp = models.BooleanField(default=False) #for podcast feeds enclosure_url = models.CharField(_('Enclosure URL'), max_length=500, blank=True) # for podcast feeds enclosure_type = models.CharField(_('Enclosure Type'), max_length=120, blank=True) # for podcast feeds enclosure_length = models.IntegerField(_('Enclosure Length'), default=0) # for podcast feeds use_auto_timestamp = models.BooleanField(_('Auto Timestamp'), default=False) # html-meta tags meta = models.OneToOneField(MetaTags, null=True) categories = GenericRelation(CategoryItem, object_id_field="object_id", content_type_field="content_type") perms = GenericRelation(ObjectPermission, object_id_field="object_id", content_type_field="content_type") objects = NewsManager() class Meta: permissions = (("view_news", _("Can view news")), ) verbose_name_plural = _("News") app_label = 'news' def get_meta(self, name): """ This method is standard across all models that are related to the Meta model. Used to generate dynamic meta information niche to this model. """ return NewsMeta().get_meta(self, name) @models.permalink def get_absolute_url(self): return ("news.detail", [self.slug]) def __unicode__(self): return self.headline def save(self, *args, **kwargs): if not self.id: self.guid = str(uuid.uuid1()) self.assign_release_dt_local() photo_upload = kwargs.pop('photo', None) super(News, self).save(*args, **kwargs) if photo_upload and self.pk: image = NewsImage(object_id=self.pk, creator=self.creator, creator_username=self.creator_username, owner=self.owner, owner_username=self.owner_username) photo_upload.file.seek(0) image.file.save(photo_upload.name, photo_upload) # save file row image.save() # save image row if self.thumbnail: self.thumbnail.delete() # delete image and file row self.thumbnail = image # set image self.save() if self.thumbnail: if self.is_public(): set_s3_file_permission(self.thumbnail.file, public=True) else: set_s3_file_permission(self.thumbnail.file, public=False) @property def category_set(self): items = {} for cat in self.categories.select_related('category__name', 'parent__name'): if cat.category: items["category"] = cat.category elif cat.parent: items["sub_category"] = cat.parent return items def is_public(self): return all([ self.allow_anonymous_view, self.status, self.status_detail in ['active'] ]) @property def is_released(self): return self.release_dt_local <= datetime.now() @property def has_google_author(self): return self.contributor_type == self.CONTRIBUTOR_AUTHOR @property def has_google_publisher(self): return self.contributor_type == self.CONTRIBUTOR_PUBLISHER def assign_release_dt_local(self): """ convert release_dt to the corresponding local time example: if release_dt: 2014-05-09 03:30:00 timezone: US/Pacific settings.TIME_ZONE: US/Central then the corresponding release_dt_local will be: 2014-05-09 05:30:00 """ now = datetime.now() now_with_tz = adjust_datetime_to_timezone(now, settings.TIME_ZONE) if self.timezone and self.release_dt and self.timezone.zone != settings.TIME_ZONE: time_diff = adjust_datetime_to_timezone( now, self.timezone) - now_with_tz self.release_dt_local = self.release_dt + time_diff else: self.release_dt_local = self.release_dt
class UserProfile(models.Model): user = models.ForeignKey(User, unique=True) timezone = TimeZoneField()
class UserProfile(ModelBase): """ The UserProfile *must* exist for each django.contrib.auth.models.User object. This may be relaxed once Dekiwiki isn't the definitive db for user info. timezone and language fields are syndicated to Dekiwiki """ # Website fields defined for the profile form # TODO: Someday this will probably need to allow arbitrary per-profile # entries, and these will just be suggestions. website_choices = [ ('website', dict( label=_(u'Website'), prefix='http://', regex='^https?://', )), ('twitter', dict( label=_(u'Twitter'), prefix='http://twitter.com/', regex='^https?://twitter.com/', )), ('github', dict( label=_(u'GitHub'), prefix='http://github.com/', regex='^https?://github.com/', )), ('stackoverflow', dict( label=_(u'StackOverflow'), prefix='http://stackoverflow.com/users/', regex='^https?://stackoverflow.com/users/', )), ('linkedin', dict( label=_(u'LinkedIn'), prefix='http://www.linkedin.com/in/', regex='^https?://www.linkedin.com/in/', )), ] class Meta: db_table = 'user_profiles' # This could be a ForeignKey, except wikidb might be # a different db deki_user_id = models.PositiveIntegerField(default=0, editable=False) timezone = TimeZoneField(null=True, blank=True, verbose_name=_(u'Timezone')) locale = LocaleField(null=True, blank=True, db_index=True, verbose_name=_(u'Language')) homepage = models.URLField(max_length=255, blank=True, default='', error_messages={ 'invalid': _(u'This URL has an invalid format. ' u'Valid URLs look like ' u'http://example.com/my_page.') }) title = models.CharField(_(u'Title'), max_length=255, default='', blank=True) fullname = models.CharField(_(u'Name'), max_length=255, default='', blank=True) organization = models.CharField(_(u'Organization'), max_length=255, default='', blank=True) location = models.CharField(_(u'Location'), max_length=255, default='', blank=True) bio = models.TextField(_(u'About Me'), blank=True) irc_nickname = models.CharField(_(u'IRC nickname'), max_length=255, default='', blank=True) tags = NamespacedTaggableManager(_(u'Tags'), blank=True) # should this user receive contentflagging emails? content_flagging_email = models.BooleanField(default=False) user = models.ForeignKey(DjangoUser, null=True, editable=False, blank=True) # HACK: Grab-bag field for future expansion in profiles # We can store arbitrary data in here and later migrate to relational # tables if the data ever needs to be indexed & queried. Otherwise, # this keeps things nicely denormalized. Ideally, access to this field # should be gated through accessors on the model to make that transition # easier. misc = JSONField(blank=True, null=True) @models.permalink def get_absolute_url(self): return ('devmo.views.profile_view', [self.user.username]) @property def websites(self): if 'websites' not in self.misc: self.misc['websites'] = {} return self.misc['websites'] @websites.setter def websites(self, value): self.misc['websites'] = value _deki_user = None @property def deki_user(self): if not settings.DEKIWIKI_ENDPOINT: # There is no deki_user, if the MindTouch API is disabled. return None if not self._deki_user: # Need to find the DekiUser corresponding to the ID from dekicompat.backends import DekiUserBackend self._deki_user = (DekiUserBackend().get_deki_user( self.deki_user_id)) return self._deki_user def gravatar_url(self, secure=True, size=220, rating='pg', default=DEFAULT_AVATAR): """Produce a gravatar image URL from email address.""" base_url = (secure and 'https://secure.gravatar.com' or 'http://www.gravatar.com') m = hashlib.md5(self.user.email.lower().encode('utf8')) return '%(base_url)s/avatar/%(hash)s?%(params)s' % dict( base_url=base_url, hash=m.hexdigest(), params=urllib.urlencode(dict(s=size, d=default, r=rating))) @property def gravatar(self): return self.gravatar_url() def __unicode__(self): return '%s: %s' % (self.id, self.deki_user_id) def allows_editing_by(self, user): if user == self.user: return True if user.is_staff or user.is_superuser: return True return False @property def mindtouch_language(self): if not self.locale: return '' return settings.LANGUAGE_DEKI_MAP[self.locale] @property def mindtouch_timezone(self): if not self.timezone: return '' base_seconds = self.timezone._utcoffset.days * 86400 offset_seconds = self.timezone._utcoffset.seconds offset_hours = (base_seconds + offset_seconds) / 3600 return "%03d:00" % offset_hours def save(self, *args, **kwargs): skip_mindtouch_put = kwargs.get('skip_mindtouch_put', False) if 'skip_mindtouch_put' in kwargs: del kwargs['skip_mindtouch_put'] super(UserProfile, self).save(*args, **kwargs) if skip_mindtouch_put: return if not settings.DEKIWIKI_ENDPOINT: # Skip if the MindTouch API is unavailable return from dekicompat.backends import DekiUserBackend DekiUserBackend.put_mindtouch_user(self.user) def wiki_activity(self): return Revision.objects.filter( creator=self.user).order_by('-created')[:5]
class Directory(TendenciBaseModel): guid = models.CharField(max_length=40) slug = SlugField(_('URL Path'), unique=True) timezone = TimeZoneField(_('Time Zone')) headline = models.CharField(max_length=200, blank=True) summary = models.TextField(blank=True) body = tinymce_models.HTMLField() source = models.CharField(max_length=300, blank=True) # logo = models.FileField(max_length=260, upload_to=file_directory, # help_text=_('Company logo. Only jpg, gif, or png images.'), # blank=True) logo_file = models.ForeignKey(File, null=True) first_name = models.CharField(_('First Name'), max_length=100, blank=True) last_name = models.CharField(_('Last Name'), max_length=100, blank=True) address = models.CharField(_('Address'), max_length=100, blank=True) address2 = models.CharField(_('Address 2'), max_length=100, blank=True) city = models.CharField(_('City'), max_length=50, blank=True) state = models.CharField(_('State'), max_length=50, blank=True) zip_code = models.CharField(_('Zip Code'), max_length=50, blank=True) country = models.CharField(_('Country'), max_length=50, blank=True) phone = models.CharField(max_length=50, blank=True) phone2 = models.CharField(_('Phone 2'), max_length=50, blank=True) fax = models.CharField(_('Fax'), max_length=50, blank=True) email = models.CharField(_('Email'), max_length=120, blank=True) email2 = models.CharField(_('Email 2'), max_length=120, blank=True) website = models.CharField(max_length=300, blank=True) renewal_notice_sent = models.BooleanField(default=False) list_type = models.CharField(_('List Type'), max_length=50, blank=True) requested_duration = models.IntegerField(_('Requested Duration'), default=0) pricing = models.ForeignKey('DirectoryPricing', null=True) activation_dt = models.DateTimeField(_('Activation Date/Time'), null=True, blank=True) expiration_dt = models.DateTimeField(_('Expiration Date/Time'), null=True, blank=True) invoice = models.ForeignKey(Invoice, blank=True, null=True) payment_method = models.CharField(_('Payment Method'), max_length=50, blank=True) syndicate = models.BooleanField(_('Include in RSS feed'), default=True) design_notes = models.TextField(_('Design Notes'), blank=True) admin_notes = models.TextField(_('Admin Notes'), blank=True) tags = TagField(blank=True) # for podcast feeds enclosure_url = models.CharField(_('Enclosure URL'), max_length=500, blank=True) enclosure_type = models.CharField(_('Enclosure Type'), max_length=120, blank=True) enclosure_length = models.IntegerField(_('Enclosure Length'), default=0) # html-meta tags meta = models.OneToOneField(MetaTags, null=True) categories = GenericRelation(CategoryItem, object_id_field="object_id", content_type_field="content_type") perms = GenericRelation(ObjectPermission, object_id_field="object_id", content_type_field="content_type") objects = DirectoryManager() class Meta: permissions = (("view_directory",_("Can view directory")),) verbose_name = _("Directory") verbose_name_plural = _("Directories") app_label = 'directories' def get_meta(self, name): """ This method is standard across all models that are related to the Meta model. Used to generate dynamic methods coupled to this instance. """ return DirectoryMeta().get_meta(self, name) @models.permalink def get_absolute_url(self): return ("directory", [self.slug]) @models.permalink def get_renew_url(self): return ("directory.renew", [self.id]) def __unicode__(self): return self.headline def save(self, *args, **kwargs): if not self.id: self.guid = str(uuid.uuid1()) super(Directory, self).save(*args, **kwargs) if self.logo: if self.is_public(): set_s3_file_permission(self.logo.name, public=True) else: set_s3_file_permission(self.logo.name, public=False) def is_public(self): return all([self.allow_anonymous_view, self.status, self.status_detail in ['active']]) @property def logo(self): """ This represents the logo FileField Originally this was a FileField, but later we added the attribute logo_file to leverage the File model. We then replaced the logo property with this convience method for backwards compatibility. """ if self.logo_file: return self.logo_file.file def get_logo_url(self): if not self.logo_file: return u'' return reverse('file', args=[self.logo_file.pk]) # Called by payments_pop_by_invoice_user in Payment model. def get_payment_description(self, inv): """ The description will be sent to payment gateway and displayed on invoice. If not supplied, the default description will be generated. """ return 'Tendenci Invoice %d for Directory: %s (%d).' % ( inv.id, self.headline, inv.object_id, ) def make_acct_entries(self, user, inv, amount, **kwargs): """ Make the accounting entries for the directory sale """ from tendenci.apps.accountings.models import Acct, AcctEntry, AcctTran from tendenci.apps.accountings.utils import make_acct_entries_initial, make_acct_entries_closing ae = AcctEntry.objects.create_acct_entry(user, 'invoice', inv.id) if not inv.is_tendered: make_acct_entries_initial(user, ae, amount) else: # payment has now been received make_acct_entries_closing(user, ae, amount) # #CREDIT directory SALES acct_number = self.get_acct_number() acct = Acct.objects.get(account_number=acct_number) AcctTran.objects.create_acct_tran(user, ae, acct, amount*(-1)) def get_acct_number(self, discount=False): if discount: return 464400 else: return 404400 def auto_update_paid_object(self, request, payment): """ Update the object after online payment is received. """ if not request.user.profile.is_superuser: self.status_detail = 'paid - pending approval' self.save() def age(self): return datetime.now() - self.create_dt @property def category_set(self): items = {} for cat in self.categories.select_related('category__name', 'parent__name'): if cat.category: items["category"] = cat.category elif cat.parent: items["sub_category"] = cat.parent return items def renew_window(self): days = get_setting('module', 'directories', 'renewaldays') days = int(days) if self.expiration_dt and datetime.now() + timedelta(days) > self.expiration_dt: return True else: return False
class News(TendenciBaseModel): guid = models.CharField(max_length=40) slug = SlugField(_('URL Path'), unique=True) timezone = TimeZoneField(_('Time Zone')) headline = models.CharField(max_length=200, blank=True) summary = models.TextField(blank=True) body = tinymce_models.HTMLField() source = models.CharField(max_length=300, blank=True) first_name = models.CharField(_('First Name'), max_length=100, blank=True) last_name = models.CharField(_('Last Name'), max_length=100, blank=True) phone = models.CharField(max_length=50, blank=True) fax = models.CharField(max_length=50, blank=True) email = models.CharField(max_length=120, blank=True) website = models.CharField(max_length=300, blank=True) release_dt = models.DateTimeField(_('Release Date/Time'), null=True, blank=True) syndicate = models.BooleanField(_('Include in RSS feed'), default=True) design_notes = models.TextField(_('Design Notes'), blank=True) group = models.ForeignKey(Group, null=True, default=None, on_delete=models.SET_NULL) tags = TagField(blank=True) #for podcast feeds enclosure_url = models.CharField(_('Enclosure URL'), max_length=500, blank=True) # for podcast feeds enclosure_type = models.CharField(_('Enclosure Type'), max_length=120, blank=True) # for podcast feeds enclosure_length = models.IntegerField(_('Enclosure Length'), default=0) # for podcast feeds use_auto_timestamp = models.BooleanField(_('Auto Timestamp')) # html-meta tags meta = models.OneToOneField(MetaTags, null=True) categories = generic.GenericRelation(CategoryItem, object_id_field="object_id", content_type_field="content_type") perms = generic.GenericRelation(ObjectPermission, object_id_field="object_id", content_type_field="content_type") objects = NewsManager() class Meta: permissions = (("view_news", "Can view news"), ) verbose_name_plural = "News" def get_meta(self, name): """ This method is standard across all models that are related to the Meta model. Used to generate dynamic meta information niche to this model. """ return NewsMeta().get_meta(self, name) @models.permalink def get_absolute_url(self): return ("news.detail", [self.slug]) def __unicode__(self): return self.headline def save(self, *args, **kwargs): if not self.id: self.guid = str(uuid.uuid1()) super(News, self).save(*args, **kwargs) @property def category_set(self): items = {} for cat in self.categories.select_related('category__name', 'parent__name'): if cat.category: items["category"] = cat.category elif cat.parent: items["sub_category"] = cat.parent return items
class User(AbstractBaseUser, PlModelMixIn): @property def remote_password(self): return hashlib.md5(self.password).hexdigest()[:12] class Meta: app_label = "core" email = models.EmailField( verbose_name='email address', max_length=255, unique=True, db_index=True, ) username = StrippedCharField(max_length=255, default="Something" ) firstname = StrippedCharField(help_text="person's given name", max_length=200) lastname = StrippedCharField(help_text="person's surname", max_length=200) phone = StrippedCharField(null=True, blank=True, help_text="phone number contact", max_length=100) user_url = models.URLField(null=True, blank=True) site = models.ForeignKey(Site, related_name='users', help_text="Site this user will be homed too") public_key = models.TextField(null=True, blank=True, max_length=1024, help_text="Public key string") is_active = models.BooleanField(default=True) is_admin = models.BooleanField(default=False) is_staff = models.BooleanField(default=True) is_readonly = models.BooleanField(default=False) is_registering = models.BooleanField(default=False) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) enacted = models.DateTimeField(null=True, default=None) policed = models.DateTimeField(null=True, default=None) backend_status = StrippedCharField(max_length=1024, default="Provisioning in progress") deleted = models.BooleanField(default=False) write_protect = models.BooleanField(default=False) timezone = TimeZoneField() dashboards = models.ManyToManyField('DashboardView', through='UserDashboardView', blank=True) objects = UserManager() deleted_objects = DeletedUserManager() USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['firstname', 'lastname'] PI_FORBIDDEN_FIELDS = ["is_admin", "site", "is_staff"] USER_FORBIDDEN_FIELDS = ["is_admin", "is_active", "site", "is_staff", "is_readonly"] def __init__(self, *args, **kwargs): super(User, self).__init__(*args, **kwargs) self._initial = self._dict # for PlModelMixIn def isReadOnlyUser(self): return self.is_readonly def get_full_name(self): # The user is identified by their email address return self.email def get_short_name(self): # The user is identified by their email address return self.email def delete(self, *args, **kwds): # so we have something to give the observer purge = kwds.get('purge',False) if purge: del kwds['purge'] try: purge = purge or observer_disabled except NameError: pass if (purge): super(User, self).delete(*args, **kwds) else: if (not self.write_protect): self.deleted = True self.enacted=None self.save(update_fields=['enacted','deleted']) @property def keyname(self): return self.email[:self.email.find('@')] def __unicode__(self): return self.email def has_perm(self, perm, obj=None): "Does the user have a specific permission?" # Simplest possible answer: Yes, always return True def has_module_perms(self, app_label): "Does the user have permissions to view the app `app_label`?" # Simplest possible answer: Yes, always return True def is_superuser(self): return False def get_dashboards(self): DEFAULT_DASHBOARDS=["Tenant"] dashboards = sorted(list(self.userdashboardviews.all()), key=attrgetter('order')) dashboards = [x.dashboardView for x in dashboards] if not dashboards: for dashboardName in DEFAULT_DASHBOARDS: dbv = DashboardView.objects.filter(name=dashboardName) if dbv: dashboards.append(dbv[0]) return dashboards # def get_roles(self): # from core.models.site import SitePrivilege # from core.models.slice import SliceMembership # # site_privileges = SitePrivilege.objects.filter(user=self) # slice_memberships = SliceMembership.objects.filter(user=self) # roles = defaultdict(list) # for site_privilege in site_privileges: # roles[site_privilege.role.role_type].append(site_privilege.site.login_base) # for slice_membership in slice_memberships: # roles[slice_membership.role.role_type].append(slice_membership.slice.name) # return roles def save(self, *args, **kwds): if not self.id: self.set_password(self.password) print "XXX", self, self.is_active, self.is_registering if self.is_active and self.is_registering: self.send_temporary_password() self.is_registering=False self.username = self.email super(User, self).save(*args, **kwds) self._initial = self._dict def send_temporary_password(self): password = User.objects.make_random_password() self.set_password(password) subject, from_email, to = 'OpenCloud Account Credentials', '*****@*****.**', str(self.email) text_content = 'This is an important message.' userUrl="http://%s/" % get_request().get_host() html_content = """<p>Your account has been created on OpenCloud. Please log in <a href="""+userUrl+""">here</a> to activate your account<br><br>Username: """+self.email+"""<br>Temporary Password: """+password+"""<br>Please change your password once you successully login into the site.</p>""" msg = EmailMultiAlternatives(subject,text_content, from_email, [to]) msg.attach_alternative(html_content, "text/html") msg.send() def can_update(self, user): from core.models import SitePrivilege _cant_update_fieldName = None if user.can_update_root(): return True # site pis can update site_privs = SitePrivilege.objects.filter(user=user, site=self.site) for site_priv in site_privs: if site_priv.role.role == 'admin': return True if site_priv.role.role == 'pi': for fieldName in self.diff.keys(): if fieldName in self.PI_FORBIDDEN_FIELDS: _cant_update_fieldName = fieldName return False return True if (user.id == self.id): for fieldName in self.diff.keys(): if fieldName in self.USER_FORBIDDEN_FIELDS: _cant_update_fieldName = fieldName return False return True return False def can_update_root(self): """ Return True if user has root (global) write access. """ if self.is_readonly: return False if self.is_admin: return True return False def can_update_deployment(self, deployment): from core.models.site import DeploymentPrivilege if self.can_update_root(): return True if DeploymentPrivilege.objects.filter( deployment=deployment, user=self, role__role__in=['admin', 'Admin']): return True return False def can_update_site(self, site, allow=[]): from core.models.site import SitePrivilege if self.can_update_root(): return True if SitePrivilege.objects.filter( site=site, user=self, role__role__in=['admin', 'Admin']+allow): return True return False def can_update_slice(self, slice): from core.models.slice import SlicePrivilege if self.can_update_root(): return True if self == slice.creator: return True if self.can_update_site(slice.site, allow=['pi']): return True if SlicePrivilege.objects.filter( slice=slice, user=self, role__role__in=['admin', 'Admin']): return True return False @staticmethod def select_by_user(user): if user.is_admin: qs = User.objects.all() else: # can see all users at any site where this user has pi role from core.models.site import SitePrivilege site_privs = SitePrivilege.objects.filter(user=user) sites = [sp.site for sp in site_privs if sp.role.role in ['Admin', 'admin', 'pi']] # get site privs of users at these sites site_privs = SitePrivilege.objects.filter(site__in=sites) user_ids = [sp.user.id for sp in site_privs] + [user.id] qs = User.objects.filter(Q(site__in=sites) | Q(id__in=user_ids)) return qs def save_by_user(self, user, *args, **kwds): if not self.can_update(user): if getattr(self, "_cant_update_fieldName", None) is not None: raise PermissionDenied("You do not have permission to update field %s on object %s" % (self._cant_update_fieldName, self.__class__.__name__)) else: raise PermissionDenied("You do not have permission to update %s objects" % self.__class__.__name__) self.save(*args, **kwds) def delete_by_user(self, user, *args, **kwds): if not self.can_update(user): raise PermissionDenied("You do not have permission to delete %s objects" % self.__class__.__name__) self.delete(*args, **kwds)
class User(AbstractBaseUser, PlModelMixIn): @property def remote_password(self): return hashlib.md5(self.password).hexdigest()[:12] class Meta: app_label = "core" email = models.EmailField( verbose_name='email address', max_length=255, unique=True, db_index=True, ) username = StrippedCharField(max_length=255, default="Something") firstname = StrippedCharField(help_text="person's given name", max_length=200) lastname = StrippedCharField(help_text="person's surname", max_length=200) phone = StrippedCharField(null=True, blank=True, help_text="phone number contact", max_length=100) user_url = models.URLField(null=True, blank=True) site = models.ForeignKey(Site, related_name='users', help_text="Site this user will be homed too") public_key = models.TextField(null=True, blank=True, max_length=1024, help_text="Public key string") is_active = models.BooleanField(default=True) is_admin = models.BooleanField(default=False) is_staff = models.BooleanField(default=True) is_readonly = models.BooleanField(default=False) is_registering = models.BooleanField(default=False) is_appuser = models.BooleanField(default=False) login_page = StrippedCharField( help_text="send this user to a specific page on login", max_length=200, null=True, blank=True) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) enacted = models.DateTimeField(null=True, default=None) policed = models.DateTimeField(null=True, default=None) backend_status = StrippedCharField(max_length=1024, default="Provisioning in progress") deleted = models.BooleanField(default=False) write_protect = models.BooleanField(default=False) lazy_blocked = models.BooleanField(default=False) no_sync = models.BooleanField(default=False) # prevent object sync no_policy = models.BooleanField(default=False) # prevent model_policy run timezone = TimeZoneField() dashboards = models.ManyToManyField('DashboardView', through='UserDashboardView', blank=True) objects = UserManager() deleted_objects = DeletedUserManager() USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['firstname', 'lastname'] PI_FORBIDDEN_FIELDS = ["is_admin", "site", "is_staff"] USER_FORBIDDEN_FIELDS = [ "is_admin", "is_active", "site", "is_staff", "is_readonly" ] def __init__(self, *args, **kwargs): super(User, self).__init__(*args, **kwargs) self._initial = self._dict # for PlModelMixIn def isReadOnlyUser(self): return self.is_readonly def get_full_name(self): # The user is identified by their email address return self.email def get_short_name(self): # The user is identified by their email address return self.email def delete(self, *args, **kwds): # so we have something to give the observer purge = kwds.get('purge', False) if purge: del kwds['purge'] try: purge = purge or observer_disabled except NameError: pass if (purge): super(User, self).delete(*args, **kwds) else: if (not self.write_protect): self.deleted = True self.enacted = None self.save(update_fields=['enacted', 'deleted']) @property def keyname(self): return self.email[:self.email.find('@')] def __unicode__(self): return self.email def has_perm(self, perm, obj=None): "Does the user have a specific permission?" # Simplest possible answer: Yes, always return True def has_module_perms(self, app_label): "Does the user have permissions to view the app `app_label`?" # Simplest possible answer: Yes, always return True def is_superuser(self): return False def get_dashboards(self): DEFAULT_DASHBOARDS = ["Tenant"] dashboards = sorted(list(self.userdashboardviews.all()), key=attrgetter('order')) dashboards = [x.dashboardView for x in dashboards] if (not dashboards) and (not self.is_appuser): for dashboardName in DEFAULT_DASHBOARDS: dbv = DashboardView.objects.filter(name=dashboardName) if dbv: dashboards.append(dbv[0]) return dashboards # def get_roles(self): # from core.models.site import SitePrivilege # from core.models.slice import SliceMembership # # site_privileges = SitePrivilege.objects.filter(user=self) # slice_memberships = SliceMembership.objects.filter(user=self) # roles = defaultdict(list) # for site_privilege in site_privileges: # roles[site_privilege.role.role_type].append(site_privilege.site.login_base) # for slice_membership in slice_memberships: # roles[slice_membership.role.role_type].append(slice_membership.slice.name) # return roles def save(self, *args, **kwds): if not self.id: self.set_password(self.password) if self.is_active and self.is_registering: self.send_temporary_password() self.is_registering = False self.username = self.email super(User, self).save(*args, **kwds) self._initial = self._dict def send_temporary_password(self): password = User.objects.make_random_password() self.set_password(password) subject, from_email, to = 'OpenCloud Account Credentials', '*****@*****.**', str( self.email) text_content = 'This is an important message.' userUrl = "http://%s/" % get_request().get_host() html_content = """<p>Your account has been created on OpenCloud. Please log in <a href=""" + userUrl + """>here</a> to activate your account<br><br>Username: """ + \ self.email + """<br>Temporary Password: """ + password + \ """<br>Please change your password once you successully login into the site.</p>""" msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) msg.attach_alternative(html_content, "text/html") msg.send() def can_update(self, user): from core.models import SitePrivilege _cant_update_fieldName = None if user.can_update_root(): return True # site pis can update site_privs = SitePrivilege.objects.filter(user=user, site=self.site) for site_priv in site_privs: if site_priv.role.role == 'admin': return True if site_priv.role.role == 'pi': for fieldName in self.diff.keys(): if fieldName in self.PI_FORBIDDEN_FIELDS: _cant_update_fieldName = fieldName return False return True if (user.id == self.id): for fieldName in self.diff.keys(): if fieldName in self.USER_FORBIDDEN_FIELDS: _cant_update_fieldName = fieldName return False return True return False def can_update_root(self): """ Return True if user has root (global) write access. """ if self.is_readonly: return False if self.is_admin: return True return False def can_update_deployment(self, deployment): from core.models.site import DeploymentPrivilege if self.can_update_root(): return True if DeploymentPrivilege.objects.filter( deployment=deployment, user=self, role__role__in=['admin', 'Admin']): return True return False def can_update_site(self, site, allow=[]): from core.models.site import SitePrivilege if self.can_update_root(): return True if SitePrivilege.objects.filter(site=site, user=self, role__role__in=['admin', 'Admin'] + allow): return True return False def can_update_slice(self, slice): from core.models.slice import SlicePrivilege if self.can_update_root(): return True if self == slice.creator: return True if self.can_update_site(slice.site, allow=['pi']): return True if SlicePrivilege.objects.filter(slice=slice, user=self, role__role__in=['admin', 'Admin']): return True return False def can_update_service(self, service, allow=[]): from core.models.service import ServicePrivilege if self.can_update_root(): return True if ServicePrivilege.objects.filter(service=service, user=self, role__role__in=['admin', 'Admin'] + allow): return True return False def can_update_tenant_root(self, tenant_root, allow=[]): from core.models.service import TenantRoot, TenantRootPrivilege if self.can_update_root(): return True if TenantRootPrivilege.objects.filter( tenant_root=tenant_root, user=self, role__role__in=['admin', 'Admin'] + allow): return True return False def can_update_tenant(self, tenant, allow=[]): from core.models.service import Tenant, TenantPrivilege if self.can_update_root(): return True if TenantPrivilege.objects.filter(tenant=tenant, user=self, role__role__in=['admin', 'Admin'] + allow): return True return False def can_update_tenant_root_privilege(self, tenant_root_privilege, allow=[]): return self.can_update_tenant_root(tenant_root_privilege.tenant_root, allow) def can_update_tenant_privilege(self, tenant_privilege, allow=[]): return self.can_update_tenant(tenant_privilege.tenant, allow) def get_readable_objects(self, filter_by=None): """ Returns a list of objects that the user is allowed to read. """ from core.models import Deployment, Flavor, Image, Network, NetworkTemplate, Node, PlModelMixIn, Site, Slice, SliceTag, Instance, Tag, User, DeploymentPrivilege, SitePrivilege, SlicePrivilege models = [] if filter_by and isinstance(filter_by, list): models = [m for m in filter_by if issubclass(m, PlModelMixIn)] if not models: models = [ Deployment, Network, Site, Slice, SliceTag, Instance, Tag, User ] readable_objects = [] for model in models: readable_objects.extend(model.select_by_user(self)) return readable_objects def get_permissions(self, filter_by=None): """ Return a list of objects for which the user has read or read/write access. The object will be an instance of a django model object. Permissions will be either 'r' or 'rw'. e.g. [{'object': django_object_instance, 'permissions': 'rw'}, ...] Returns: list of dicts """ from core.models import Deployment, Flavor, Image, Network, NetworkTemplate, Node, PlModelMixIn, Site, Slice, SliceTag, Instance, Tag, User, DeploymentPrivilege, SitePrivilege, SlicePrivilege READ = 'r' READWRITE = 'rw' models = [] if filter_by and isinstance(filter_by, list): models = [m for m in filter_by if issubclass(m, PlModelMixIn)] deployment_priv_objs = [Image, NetworkTemplate, Flavor] site_priv_objs = [Node, Slice, User] slice_priv_objs = [Instance, Network] # maps the set of objects a paticular role has write access write_map = { DeploymentPrivilege: { 'admin': deployment_priv_objects, }, SitePrivilege: { 'admin': site_priv_objs, 'pi': [Slice, User], 'tech': [Node], }, SlicePrivilege: { 'admin': slice_priv_objs, }, } privilege_map = { DeploymentPrivilege: (Deployment, deployment_priv_objs), SitePrivilege: (Site, site_priv_objs), SlicePrivilege: (Slice, slice_priv_objs) } permissions = [] permission_dict = lambda x, y: {'object': x, 'permission': y} for privilege_model, (model, affected_models) in privileg_map.items(): if models and model not in models: continue # get the objects affected by this privilege model affected_objects = [] for affected_model in affected_models: affected_objects.extend(affected_model.select_by_user(self)) if self.is_admin: # assume admin users have read/write access to all objects for affected_object in affected_objects: permissions.append( permission_dict(affected_object, READWRITE)) else: # create a dict of the user's per object privileges # ex: {princeton_tmack : ['admin'] privileges = privilege_model.objects.filter(user=self) for privilege in privileges: object_roles = defaultdict(list) obj = None roles = [] for field in dir(privilege): if field == model.__name__.lower(): obj = getattr(privilege, field) if obj: object_roles[obj].append(privilege.role.role) # loop through all objects the user has access to and determine # if they also have write access for affected_object in affected_objects: if affected_object not in objects_roles: permissions.append( permission_dict(affected_object, READ)) else: has_write_permission = False for write_role, models in write_dict.items(): if affected_object._meta.model in models and \ write_role in object_roles[affected_object]: has_write_permission = True break if has_write_permission: permissions.append( permission_dict(affected_object, WRITE)) else: permissions.append( permission_dict(affected_object, READ)) return permissions def get_tenant_permissions(self): from core.models import Site, Slice return self.get_object_permissions(filter_by=[Site, Slice]) @staticmethod def select_by_user(user): if user.is_admin: qs = User.objects.all() else: # can see all users at any site where this user has pi role from core.models.site import SitePrivilege site_privs = SitePrivilege.objects.filter(user=user) sites = [ sp.site for sp in site_privs if sp.role.role in ['Admin', 'admin', 'pi'] ] # get site privs of users at these sites site_privs = SitePrivilege.objects.filter(site__in=sites) user_ids = [sp.user.id for sp in site_privs] + [user.id] qs = User.objects.filter(Q(site__in=sites) | Q(id__in=user_ids)) return qs def save_by_user(self, user, *args, **kwds): if not self.can_update(user): if getattr(self, "_cant_update_fieldName", None) is not None: raise PermissionDenied( "You do not have permission to update field %s on object %s" % (self._cant_update_fieldName, self.__class__.__name__)) else: raise PermissionDenied( "You do not have permission to update %s objects" % self.__class__.__name__) self.save(*args, **kwds) def delete_by_user(self, user, *args, **kwds): if not self.can_update(user): raise PermissionDenied( "You do not have permission to delete %s objects" % self.__class__.__name__) self.delete(*args, **kwds) def apply_profile(self, profile): if profile == "regular": self.is_appuser = False self.is_admin = False elif profile == "cp": self.is_appuser = True self.is_admin = False for db in self.userdashboardviews.all(): db.delete()
class UserProfile(ModelBase): """ The UserProfile *must* exist for each django.contrib.auth.models.User object. This may be relaxed once Dekiwiki isn't the definitive db for user info. timezone and language fields are syndicated to Dekiwiki """ # This could be a ForeignKey, except wikidb might be # a different db deki_user_id = models.PositiveIntegerField(default=0, editable=False) timezone = TimeZoneField(null=True, blank=True, verbose_name=_(u'Timezone')) locale = LocaleField(null=True, blank=True, db_index=True, verbose_name=_(u'Language')) homepage = models.URLField(max_length=255, blank=True, default='', error_messages={ 'invalid': _(u'This URL has an invalid format. ' u'Valid URLs look like ' u'http://example.com/my_page.') }) title = models.CharField(_(u'Title'), max_length=255, default='', blank=True) fullname = models.CharField(_(u'Name'), max_length=255, default='', blank=True) organization = models.CharField(_(u'Organization'), max_length=255, default='', blank=True) location = models.CharField(_(u'Location'), max_length=255, default='', blank=True) bio = models.TextField(_(u'About Me'), blank=True) irc_nickname = models.CharField(_(u'IRC nickname'), max_length=255, default='', blank=True) tags = NamespacedTaggableManager(_(u'Tags'), blank=True) # should this user receive contentflagging emails? content_flagging_email = models.BooleanField(default=False) user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, editable=False, blank=True) # HACK: Grab-bag field for future expansion in profiles # We can store arbitrary data in here and later migrate to relational # tables if the data ever needs to be indexed & queried. Otherwise, # this keeps things nicely denormalized. Ideally, access to this field # should be gated through accessors on the model to make that transition # easier. misc = JSONField(blank=True, null=True) @property def websites(self): if 'websites' not in self.misc: self.misc['websites'] = {} return self.misc['websites'] @websites.setter def websites(self, value): self.misc['websites'] = value class Meta: db_table = 'user_profiles' def __unicode__(self): return '%s: %s' % (self.id, self.deki_user_id) def get_absolute_url(self): return self.user.get_absolute_url()
class Profile(models.Model): name = models.CharField(max_length=100) timezone = TimeZoneField()
class UserProfile(models.Model): user = models.OneToOneField(User) created_at = models.DateTimeField('Created at', auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) timezone = TimeZoneField('your local timezone', default=settings.TIME_ZONE)
class User(AbstractBaseUser, PlModelMixIn): plural_name = "Users" @property def remote_password(self): return hashlib.md5(self.password).hexdigest()[:12] class Meta: app_label = "core" email = models.EmailField( verbose_name='email address', max_length=255, unique=True, db_index=True, ) username = StrippedCharField(max_length=255, default="Something") firstname = StrippedCharField(help_text="person's given name", max_length=200) lastname = StrippedCharField(help_text="person's surname", max_length=200) phone = StrippedCharField(null=True, blank=True, help_text="phone number contact", max_length=100) user_url = models.URLField(null=True, blank=True) site = models.ForeignKey('Site', related_name='users', help_text="Site this user will be homed too") public_key = models.TextField(null=True, blank=True, max_length=1024, help_text="Public key string") is_active = models.BooleanField(default=True) is_admin = models.BooleanField(default=False) is_staff = models.BooleanField(default=True) is_readonly = models.BooleanField(default=False) is_registering = models.BooleanField(default=False) is_appuser = models.BooleanField(default=False) login_page = StrippedCharField( help_text="send this user to a specific page on login", max_length=200, null=True, blank=True) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) enacted = models.DateTimeField(null=True, default=None) policed = models.DateTimeField(null=True, default=None) backend_status = StrippedCharField(max_length=1024, default="Provisioning in progress") backend_need_delete = models.BooleanField(default=False) backend_need_reap = models.BooleanField(default=False) deleted = models.BooleanField(default=False) write_protect = models.BooleanField(default=False) lazy_blocked = models.BooleanField(default=False) no_sync = models.BooleanField(default=False) # prevent object sync no_policy = models.BooleanField(default=False) # prevent model_policy run timezone = TimeZoneField() dashboards = models.ManyToManyField('DashboardView', through='UserDashboardView', blank=True) policy_status = models.CharField(default="0 - Policy in process", max_length=1024, null=True) objects = UserManager() deleted_objects = DeletedUserManager() USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['firstname', 'lastname'] PI_FORBIDDEN_FIELDS = ["is_admin", "site", "is_staff"] USER_FORBIDDEN_FIELDS = [ "is_admin", "is_active", "site", "is_staff", "is_readonly" ] def __init__(self, *args, **kwargs): super(User, self).__init__(*args, **kwargs) self._initial = self._dict # for PlModelMixIn self.silent = False def isReadOnlyUser(self): return self.is_readonly def get_full_name(self): # The user is identified by their email address return self.email def get_short_name(self): # The user is identified by their email address return self.email @property def keyname(self): return self.email[:self.email.find('@')] def __unicode__(self): return self.email def has_perm(self, perm, obj=None): "Does the user have a specific permission?" # Simplest possible answer: Yes, always return True def has_module_perms(self, app_label): "Does the user have permissions to view the app `app_label`?" # Simplest possible answer: Yes, always return True def is_superuser(self): return False def get_dashboards(self): DEFAULT_DASHBOARDS = ["Tenant"] dashboards = sorted(list(self.userdashboardviews.all()), key=attrgetter('order')) dashboards = [x.dashboardView for x in dashboards] if (not dashboards) and (not self.is_appuser): for dashboardName in DEFAULT_DASHBOARDS: dbv = dashboardview.DashboardView.objects.filter( name=dashboardName) if dbv: dashboards.append(dbv[0]) return dashboards # def get_roles(self): # from core.models.site import SitePrivilege # from core.models.slice import SliceMembership # # site_privileges = SitePrivilege.objects.filter(user=self) # slice_memberships = SliceMembership.objects.filter(user=self) # roles = defaultdict(list) # for site_privilege in site_privileges: # roles[site_privilege.role.role_type].append(site_privilege.site.login_base) # for slice_membership in slice_memberships: # roles[slice_membership.role.role_type].append(slice_membership.slice.name) # return roles def delete(self, *args, **kwds): # so we have something to give the observer purge = kwds.get('purge', False) if purge: del kwds['purge'] silent = kwds.get('silent', False) if silent: del kwds['silent'] try: purge = purge or observer_disabled except NameError: pass if (purge): super(User, self).delete(*args, **kwds) else: if (not self.write_protect): self.deleted = True self.enacted = None self.policed = None self.save(update_fields=['enacted', 'deleted', 'policed'], silent=silent) collector = XOSCollector( using=router.db_for_write(self.__class__, instance=self)) collector.collect([self]) with transaction.atomic(): for (k, models) in collector.data.items(): for model in models: if model.deleted: # in case it's already been deleted, don't delete again continue model.deleted = True model.enacted = None model.policed = None model.save(update_fields=[ 'enacted', 'deleted', 'policed' ], silent=silent) def save(self, *args, **kwargs): if not self.id: self.set_password(self.password) if self.is_active and self.is_registering: self.send_temporary_password() self.is_registering = False # let the user specify silence as either a kwarg or an instance varible silent = self.silent if "silent" in kwargs: silent = silent or kwargs.pop("silent") caller_kind = "unknown" if ('synchronizer' in threading.current_thread().name): caller_kind = "synchronizer" if "caller_kind" in kwargs: caller_kind = kwargs.pop("caller_kind") always_update_timestamp = False if "always_update_timestamp" in kwargs: always_update_timestamp = always_update_timestamp or kwargs.pop( "always_update_timestamp") # SMBAKER: if an object is trying to delete itself, or if the observer # is updating an object's backend_* fields, then let it slip past the # composite key check. ignore_composite_key_check = False if "update_fields" in kwargs: ignore_composite_key_check = True for field in kwargs["update_fields"]: if not (field in [ "backend_register", "backend_status", "deleted", "enacted", "updated" ]): ignore_composite_key_check = False if (caller_kind != "synchronizer") or always_update_timestamp: self.updated = timezone.now() self.username = self.email super(User, self).save(*args, **kwargs) self.push_redis_event() self._initial = self._dict def send_temporary_password(self): password = User.objects.make_random_password() self.set_password(password) subject, from_email, to = 'OpenCloud Account Credentials', '*****@*****.**', str( self.email) text_content = 'This is an important message.' userUrl = "http://%s/" % get_request().get_host() html_content = """<p>Your account has been created on OpenCloud. Please log in <a href=""" + userUrl + """>here</a> to activate your account<br><br>Username: """ + \ self.email + """<br>Temporary Password: """ + password + \ """<br>Please change your password once you successully login into the site.</p>""" msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) msg.attach_alternative(html_content, "text/html") msg.send() def apply_profile(self, profile): if profile == "regular": self.is_appuser = False self.is_admin = False elif profile == "cp": self.is_appuser = True self.is_admin = False for db in self.userdashboardviews.all(): db.delete() def get_content_type_key(self): ct = ContentType.objects.get_for_model(self.__class__) return "%s.%s" % (ct.app_label, ct.model) @staticmethod def get_content_type_from_key(key): (app_name, model_name) = key.split(".") return ContentType.objects.get_by_natural_key(app_name, model_name) @staticmethod def get_content_object(content_type, object_id): ct = User.get_content_type_from_key(content_type) cls = ct.model_class() return cls.objects.get(id=object_id) ''' This function is hardcoded here because we do not yet generate the User class''' def can_access(self, ctx): return security.user_policy_security_check(self, ctx), "user_policy"
class Profile(BaseProfile): """ The base profile model which contains fields that pertain to everyone. Should be left out of the admin since only subclasses are created. (??? -sfh) Who is this person following? pr = Profile.objects.get(id=7455) pr.followees.all() Who is following this person? pr.followers.all() Add a new followee: otheruser = Profile.objects.get(id=38) pr.followees.add(otheruser) Remove a followee: pr.followees.remove(otheruser) """ user = models.OneToOneField(User, primary_key=True) suffix = models.IntegerField(max_length=2, blank=True, null=True, choices=constants.PROFILE_SUFFIX_CHOICES) salutation = models.IntegerField( max_length=2, blank=True, null=True, choices=constants.PROFILE_SALUTATION_CHOICES) middle_name = models.CharField(max_length=50, blank=True, null=True) title = models.CharField(blank=True, null=True, max_length=128) about = models.TextField( blank=True, null=True, help_text= "A few sentences about yourself - capsule biography. No HTML allowed.") email2 = models.EmailField('Secondary Email', blank=True, null=True) home_phone1 = models.CharField('Home Phone', max_length=60, blank=True, null=True) biz_phone1 = models.CharField('Business Phone', max_length=60, blank=True, null=True) mobile_phone1 = models.CharField('Mobile Phone', max_length=60, blank=True, null=True) fax = models.CharField(max_length=60, blank=True, null=True) timezone = TimeZoneField() allow_contact = models.BooleanField( default=True, help_text='Allow the public to contact you through CalCentral.') show_name = models.BooleanField( default=True, help_text='Not currently implemented, for future use.') avatar = ImageField( upload_to=get_avatar_path, blank=True, null=True, help_text= 'Upload an avatar/image/icon to represent you on the site.<br />Please make sure your image is mostly square, not rectangular.' ) url_personal = models.URLField('Personal website', blank=True, null=True, verify_exists=True) url_org = models.URLField('Organization website', blank=True, null=True, verify_exists=True) accepted_terms = models.BooleanField( default=False, help_text= "All users must accept our terms and conditions before doing anything on the site." ) followees = models.ManyToManyField( 'self', blank=True, null=True, related_name='followers', symmetrical=False, help_text='People this person is following.') # Preferences email_on_follow = models.BooleanField( default=True, help_text='Receive email when someone follows you.') # Model Managers active_objects = ActiveProfileManager() alumni_objects = ActiveProfileAlumniManager() staff_objects = StaffProfileManager() emp_objects = EmployeeProfileManager() def __unicode__(self): return self.get_display_name() def get_display_name(self): if self.user.first_name and self.user.last_name: # and self.show_real_name: display_name = "%s %s" % ( self.user.first_name, self.user.last_name, ) return display_name else: return self.user.username def phones_all(self): """ Return a dict of all phone data. """ return dict(home=self.home_phone1, mobile=self.mobile_phone1, work=self.biz_phone1) def is_staff(self): """ Return True if the person is in the Staff group. Note: this is different from user.is_staff() which is a similar boolean flag that allows users to access the django admin. """ if not self.user.is_active: return False #if self.user.is_staff(): return True if Group.objects.get(name="Staff") in self.user.groups.all(): return True return False def is_instructor(self): """ Return True if this person is in one of the Instructor groups. """ if not self.user.is_active: return False for g in INSTRUCTOR_GROUPS: if Group.objects.get(name=g) in self.user.groups.all(): return True return False def is_student(self): """ Return True if this person is in the Student group. """ if not self.user.is_active: return False if Group.objects.get(name="Students") in self.user.groups.all(): return True return False def is_alumni(self): """ Return True if this person is active and in the Alumni group. """ if not self.user.is_active: return False if Group.objects.get(name="Alumni") in self.user.groups.all(): return True return False def is_affiliated(self): """ Need this in some places such as whether to show Private events (we don't show) them to alumni or to "basic" users. """ if not self.user.is_active: return False if self.is_staff() or self.is_instructor() or self.is_student(): return True return False def in_group(self, group): """ Return True if the user/profile is in the group. Requires a string or a Group object as argument. """ if type(group) == unicode or type(group) == str: return bool(self.user.groups.filter(name=group)) if group in self.user.groups.all(): return True return False def is_alumni_only(self): """ Return True if a profile is only in the alumni group but not also staff or instructor. Useful to rendering the correct nav, for example. """ if self.is_alumni( ) and not self.is_staff() and not self.is_instructor(): return True else: return False def get_form_name(self): return "%sForm" % self._meta.module_name.title() def get_primary_email(self): """ Return user's primary email address. """ return self.user.email