import logging from django.db import models from pingcap_sso.db.fields import DateTimePGUTCField logger = logging.getLogger(__name__) class DiscourseUser(models.Model): username = models.CharField(max_length=60) created_at = DateTimePGUTCField(auto_now_add=True) updated_at = DateTimePGUTCField(auto_now=True) name = models.CharField(max_length=255, default=None, blank=True, null=True) seen_notification_id = models.IntegerField(default=0) active = models.IntegerField(default=0) username_lower = models.CharField(max_length=60) admin = models.IntegerField(default=0) moderator = models.BooleanField(default=False) approved = models.IntegerField(default=0) ip_address = models.GenericIPAddressField(blank=True, null=True) trust_level = models.IntegerField(default=0) title = models.CharField(max_length=255, blank=True, null=True) flair_group_id = models.IntegerField(blank=True, null=True) class Meta: db_table = 'users' managed = False def get_sso_user(self, log_error_if_not_exists=True): from pingcap_sso.models import User if self.id < 0: # It's a bot, does not have sso account. if log_error_if_not_exists: logger.error('You are trying to get sso user for a bot') return None try: external_id = DiscourseSingleSignOnRecord.objects.get(user=self).external_id sso_user = User.objects.get(openid=external_id) return sso_user except DiscourseSingleSignOnRecord.DoesNotExist: if log_error_if_not_exists: logger.error(f'AskTUG user({self.id}) do not have single-sign-on record') except User.DoesNotExist: if log_error_if_not_exists: logger.error(f'SSO user does not found by external_id({external_id})') return None class DiscourseSingleSignOnRecord(models.Model): user = models.ForeignKey('discourse.DiscourseUser', on_delete=models.DO_NOTHING) external_id = models.CharField(max_length=255) last_payload = models.TextField() created_at = DateTimePGUTCField(auto_now_add=True) updated_at = DateTimePGUTCField(auto_now=True) external_username = models.CharField(max_length=255, null=True) external_email = models.CharField(max_length=255, null=True) external_name = models.CharField(max_length=255, null=True) external_avatar_url = models.CharField(max_length=1000, null=True) external_profile_background_url = models.CharField(max_length=255, null=True) external_card_background_url = models.CharField(max_length=255, null=True) class Meta: db_table = 'single_sign_on_records' managed = False class DiscourseUserAuthToken(models.Model): user = models.ForeignKey('discourse.DiscourseUser', on_delete=models.DO_NOTHING) auth_token = models.CharField(max_length=255) prev_auth_token = models.CharField(max_length=255) user_agent = models.TextField() auth_token_seen = models.BooleanField(default=False) client_ip = models.GenericIPAddressField(null=True) rotated_at = DateTimePGUTCField() created_at = DateTimePGUTCField() updated_at = DateTimePGUTCField() seen_at = DateTimePGUTCField() class Meta: db_table = 'user_auth_tokens' managed = False class DiscourseUserAuthTokenLog(models.Model): action = models.CharField(max_length=255) user_auth_token = models.ForeignKey('discourse.DiscourseUserAuthToken', on_delete=models.DO_NOTHING) user = models.ForeignKey('discourse.DiscourseUser', on_delete=models.DO_NOTHING) client_ip = models.GenericIPAddressField(null=True) user_agent = models.TextField(null=True) auth_token = models.CharField(max_length=255, null=True) created_at = DateTimePGUTCField(auto_now_add=True) path = models.CharField(max_length=255, null=True) class Meta: db_table = 'user_auth_token_logs' managed = False class DiscourseUserEmail(models.Model): user = models.ForeignKey('discourse.DiscourseUser', on_delete=models.DO_NOTHING) email = models.EmailField() primary = models.BooleanField(default=False) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) normalized_email = models.EmailField() class Meta: db_table = 'user_emails' managed = False class DiscourseUserStat(models.Model): user = models.OneToOneField( 'discourse.DiscourseUser', on_delete=models.DO_NOTHING, primary_key=True ) topics_entered = models.IntegerField(default=0) time_read = models.IntegerField(default=0) days_visited = models.IntegerField(default=0) posts_read_count = models.IntegerField(default=0) likes_given = models.IntegerField(default=0) likes_received = models.IntegerField(default=0) new_since = DateTimePGUTCField(auto_now_add=True) read_faq = DateTimePGUTCField(blank=True, null=True) first_post_created_at = DateTimePGUTCField(blank=True, null=True) post_count = models.IntegerField(default=0) topic_count = models.IntegerField(default=0) bounce_score = models.FloatField(default=0) reset_bounce_score_after = DateTimePGUTCField(blank=True, null=True) flags_agreed = models.IntegerField(default=0) flags_disagreed = models.IntegerField(default=0) flags_ignored = models.IntegerField(default=0) first_unread_at = DateTimePGUTCField(auto_now_add=True) distinct_badge_count = models.IntegerField(default=0) first_unread_pm_at = DateTimePGUTCField(auto_now_add=True) digest_attempted_at = DateTimePGUTCField() post_edits_count = models.IntegerField(default=0) draft_count = models.IntegerField(default=0) pending_posts_count = models.IntegerField(default=0) class Meta: db_table = 'user_stats' managed = False class DiscourseUserSearchData(models.Model): user_id = models.IntegerField(primary_key=True) search_data = models.TextField() raw_data = models.TextField() locale = models.TextField(default='zh_CN') version = models.IntegerField(default=3) class Meta: db_table = 'user_search_data' managed = False class DiscourseUserProfile(models.Model): user = models.OneToOneField( 'discourse.DiscourseUser', on_delete=models.DO_NOTHING, primary_key=True ) location = models.TextField(default=None, null=True) website = models.TextField(default=None, null=True) bio_raw = models.TextField(default=None, null=True) bio_cooked = models.TextField(default=None, null=True) bio_cooked_version = models.IntegerField(default=1) class Meta: db_table = 'user_profiles' managed = False class DiscourseUserOption(models.Model): user = models.OneToOneField( 'discourse.DiscourseUser', on_delete=models.DO_NOTHING, primary_key=True ) theme_ids = models.JSONField(default=list) email_digests = models.BooleanField(default=True) enable_quoting = models.BooleanField(default=True) digest_after_minutes = models.IntegerField(default=10080) auto_track_topics_after_msecs = models.IntegerField(default=240000) new_topic_duration_minutes = models.IntegerField(default=2880) email_previous_replies = models.IntegerField(default=2) email_in_reply_to = models.IntegerField(default=1) class Meta: db_table = 'user_options' managed = False class DiscourseUserCustomField(models.Model): user = models.ForeignKey('discourse.DiscourseUser', on_delete=models.DO_NOTHING) name = models.CharField(max_length=255) value = models.TextField() created_at = DateTimePGUTCField(auto_now_add=True) updated_at = DateTimePGUTCField(auto_now=True) class Meta: db_table = 'user_custom_fields' managed = False class DiscourseGroup(models.Model): name = models.CharField(max_length=255, unique=True) automatic = models.BooleanField(default=False) user_count = models.IntegerField(default=0) automatic_membership_email_domains = models.TextField(blank=True, null=True) primary_group = models.BooleanField(default=False) title = models.CharField(max_length=255, blank=True, null=True) grant_trust_level = models.IntegerField(blank=True, null=True) incoming_email = models.CharField(max_length=255, blank=True, null=True, unique=True) has_messages = models.BooleanField(default=False) flair_bg_color = models.CharField(max_length=255, blank=True, null=True) flair_color = models.CharField(max_length=255, blank=True, null=True) bio_raw = models.TextField(blank=True, null=True) bio_cooked = models.TextField(blank=True, null=True) allow_membership_requests = models.BooleanField(default=False) full_name = models.CharField(max_length=255, blank=True, null=True) default_notification_level = models.IntegerField(default=3) visibility_level = models.IntegerField(default=0) public_exit = models.BooleanField(default=False) public_admission = models.BooleanField(default=False) membership_request_template = models.TextField(blank=True, null=True) messageable_level = models.IntegerField(default=0) mentionable_level = models.IntegerField(default=0) created_at = DateTimePGUTCField(auto_now_add=True) updated_at = DateTimePGUTCField(auto_now=True) class Meta: db_table = 'groups' managed = False class DiscourseGroupUser(models.Model): group = models.ForeignKey('discourse.DiscourseGroup', on_delete=models.DO_NOTHING) user = models.ForeignKey('discourse.DiscourseUser', on_delete=models.DO_NOTHING) owner = models.BooleanField(default=False) notification_level = models.IntegerField(default=2) first_unread_pm_at = DateTimePGUTCField(auto_now_add=True) created_at = DateTimePGUTCField(auto_now_add=True) updated_at = DateTimePGUTCField(auto_now=True) class Meta: db_table = 'group_users' managed = False class DiscourseTopicCustomField(models.Model): topic = models.ForeignKey('discourse.DiscourseTopic', on_delete=models.DO_NOTHING) name = models.CharField(max_length=255) value = models.TextField() created_at = DateTimePGUTCField(auto_now_add=True) updated_at = DateTimePGUTCField(auto_now=True) class Meta: db_table = 'topic_custom_fields' managed = False class DiscourseTopicView(models.Model): topic = models.ForeignKey('discourse.DiscourseTopic', on_delete=models.DO_NOTHING) viewed_at = models.DateField() user = models.ForeignKey( 'discourse.DiscourseUser', on_delete=models.DO_NOTHING, null=True, blank=True ) ip_address = models.GenericIPAddressField(blank=True, null=True) class Meta: db_table = 'topic_views' managed = False class DiscourseTopic(models.Model): title = models.CharField(max_length=255) last_posted_at = DateTimePGUTCField(blank=True, null=True) created_at = DateTimePGUTCField(auto_now_add=True) updated_at = DateTimePGUTCField(auto_now=True) views = models.IntegerField(default=0) posts_count = models.IntegerField(default=0) user = models.ForeignKey('discourse.DiscourseUser', on_delete=models.DO_NOTHING) last_post_user_id = models.IntegerField() reply_count = models.IntegerField(default=0) deleted_at = DateTimePGUTCField(blank=True, null=True) like_count = models.IntegerField(default=0) category = models.ForeignKey( 'discourse.DiscourseCategory', on_delete=models.DO_NOTHING, blank=True, null=True) visible = models.BooleanField(default=True) closed = models.BooleanField(default=False) archived = models.BooleanField(default=False) bumped_at = DateTimePGUTCField() has_summary = models.BooleanField(default=False) archetype = models.CharField(max_length=255, default='regular') spam_count = models.IntegerField(default=0) pinned_at = DateTimePGUTCField() score = models.FloatField(blank=True, null=True) percent_rank = models.FloatField(default=1) slug = models.CharField(max_length=255) deleted_by_id = models.IntegerField() word_count = models.IntegerField(blank=True, null=True) excerpt = models.CharField(max_length=1000) pinned_globally = models.BooleanField(default=False) pinned_until = DateTimePGUTCField(blank=True, null=True) fancy_title = models.CharField(max_length=400) participant_count = models.IntegerField(default=1) class Meta: db_table = 'topics' managed = False class DiscoursePost(models.Model): user = models.ForeignKey('discourse.DiscourseUser', on_delete=models.DO_NOTHING) topic = models.ForeignKey('discourse.DiscourseTopic', on_delete=models.DO_NOTHING) post_number = models.IntegerField() raw = models.TextField() cooked = models.TextField() created_at = DateTimePGUTCField(auto_now_add=True) updated_at = DateTimePGUTCField(auto_now=True) reply_to_post_number = models.IntegerField(blank=True, null=True) reply_count = models.IntegerField(default=0) quote_count = models.IntegerField(default=0) deleted_at = DateTimePGUTCField(blank=True, null=True) like_count = models.IntegerField(default=0) reads = models.IntegerField(default=0) post_type = models.IntegerField(default=1) sort_order = models.IntegerField(blank=True, null=True) last_editor = models.ForeignKey( 'discourse.DiscourseUser', on_delete=models.DO_NOTHING, related_name='edited_topics') hidden = models.BooleanField(default=False) hidden_at = DateTimePGUTCField(blank=True, null=True) deleted_by = models.ForeignKey( 'discourse.DiscourseUser', on_delete=models.DO_NOTHING, related_name='deleted_topics', blank=True, null=True) version = models.IntegerField(default=1) locked_by = models.ForeignKey( 'discourse.DiscourseUser', on_delete=models.DO_NOTHING, related_name='locked_topics', blank=True, null=True) action_code = models.CharField(max_length=255, blank=True, null=True) class Meta: unique_together = ('topic', 'post_number') db_table = 'posts' managed = False class DiscourseUpload(models.Model): user = models.ForeignKey('discourse.DiscourseUser', on_delete=models.DO_NOTHING) original_filename = models.TextField() filesize = models.IntegerField() width = models.IntegerField() height = models.IntegerField() url = models.TextField() created_at = DateTimePGUTCField(auto_now_add=True) updated_at = DateTimePGUTCField(auto_now=True) sha1 = models.CharField(max_length=40) origin = models.CharField(max_length=1000) retain_hours = models.IntegerField() extension = models.CharField(max_length=10) thumbnail_width = models.IntegerField() thumbnail_height = models.IntegerField() etag = models.CharField(max_length=255) secure = models.BooleanField(default=False) access_control_post_id = models.IntegerField() original_sha1 = models.CharField(max_length=255) animated = models.BooleanField(default=False) verification_status = models.IntegerField(default=1) security_last_changed_at = DateTimePGUTCField() security_last_changed_reason = models.TextField() dominant_color = models.TextField() class Meta: db_table = 'uploads' managed = False class DiscourseBadge(models.Model): name = models.CharField(max_length=255, unique=True) description = models.TextField(blank=True, null=True) badge_type_id = models.IntegerField() grant_count = models.IntegerField(default=0) enabled = models.BooleanField(default=True) icon = models.CharField(max_length=255, blank=True, null=True) image = models.CharField(max_length=255, blank=True, null=True) image_upload = models.ForeignKey( 'discourse.DiscourseUpload', on_delete=models.DO_NOTHING, blank=True, null=True) created_at = DateTimePGUTCField(auto_now_add=True) updated_at = DateTimePGUTCField(auto_now=True) class Meta: db_table = 'badges' managed = False class DiscourseUserBadge(models.Model): badge = models.ForeignKey('discourse.DiscourseBadge', on_delete=models.DO_NOTHING) user = models.ForeignKey('discourse.DiscourseUser', on_delete=models.DO_NOTHING) granted_at = DateTimePGUTCField(auto_now_add=True) granted_by_id = models.IntegerField() post = models.ForeignKey( 'discourse.DiscoursePost', on_delete=models.DO_NOTHING, blank=True, null=True) notification_id = models.IntegerField(blank=True, null=True) seq = models.IntegerField(default=0) class Meta: unique_together = ('badge', 'user', 'post') db_table = 'user_badges' managed = False class DiscourseCategory(models.Model): name = models.CharField(max_length=50) topic_id = models.IntegerField(blank=True, null=True) topic_count = models.IntegerField(default=0) created_at = DateTimePGUTCField(auto_now_add=True) updated_at = DateTimePGUTCField(auto_now=True) user = models.ForeignKey('discourse.DiscourseUser', on_delete=models.DO_NOTHING) slug = models.CharField(max_length=255) description = models.TextField() color = models.CharField(max_length=6, default='0088CC') parent_category = models.ForeignKey( 'self', blank=True, null=True, on_delete=models.DO_NOTHING) class Meta: db_table = 'categories' managed = False class DiscourseTag(models.Model): name = models.CharField(max_length=255, unique=True) topic_count = models.IntegerField(default=0) pm_topic_count = models.IntegerField(default=0) lower_tag_name = models.CharField(max_length=255, unique=True) created_at = DateTimePGUTCField(auto_now_add=True) updated_at = DateTimePGUTCField(auto_now=True) class Meta: db_table = 'tags' managed = False class DiscourseTopicTag(models.Model): topic = models.ForeignKey( 'discourse.DiscourseTopic', on_delete=models.DO_NOTHING ) tag = models.ForeignKey( 'discourse.DiscourseTag', on_delete=models.DO_NOTHING ) created_at = DateTimePGUTCField(auto_now_add=True) updated_at = DateTimePGUTCField(auto_now=True) class Meta: db_table = 'topic_tags' managed = False class DiscourseUserAction(models.Model): ACTION_LIKE = 1 ACTION_WAS_LIKED = 2 # NOTE: Previously type 3 was replaced by bookmark model # ACTION_BOOKMARK = 3 ACTION_NEW_TOPIC = 4 ACTION_REPLY = 5 ACTION_RESPONSE = 6 ACTION_MENTION = 7 ACTION_QUOTE = 9 ACTION_EDIT = 11 ACTION_NEW_PRIVATE_MESSAGE = 12 ACTION_GOT_PRIVATE_MESSAGE = 13 ACTION_SOLVED = 15 ACTION_ASSIGNED = 16 action_type = models.IntegerField() user = models.ForeignKey('discourse.DiscourseUser', on_delete=models.DO_NOTHING) target_topic = models.ForeignKey( 'discourse.DiscourseTopic', on_delete=models.DO_NOTHING, blank=True, null=True) target_post = models.ForeignKey( 'discourse.DiscoursePost', on_delete=models.DO_NOTHING, blank=True, null=True) target_user = models.ForeignKey( 'discourse.DiscourseUser', on_delete=models.DO_NOTHING, blank=True, null=True, related_name='user_action_target') acting_user = models.ForeignKey( 'discourse.DiscourseUser', on_delete=models.DO_NOTHING, blank=True, null=True, related_name='user_action_acting') created_at = DateTimePGUTCField(auto_now_add=True) updated_at = DateTimePGUTCField(auto_now=True) class Meta: db_table = 'user_actions' managed = False class DiscourseBookmark(models.Model): user = models.ForeignKey('discourse.DiscourseUser', on_delete=models.DO_NOTHING) post = models.ForeignKey('discourse.DiscoursePost', on_delete=models.DO_NOTHING) name = models.CharField(max_length=100, blank=True, null=True) reminder_at = DateTimePGUTCField(blank=True, null=True) created_at = DateTimePGUTCField(auto_now_add=True) updated_at = DateTimePGUTCField(auto_now=True) reminder_last_sent_at = DateTimePGUTCField(blank=True, null=True) reminder_set_at = DateTimePGUTCField(blank=True, null=True) auto_delete_preference = models.IntegerField(default=0) pinned = models.BooleanField(default=False) for_topic = models.BooleanField(default=False) bookmarkable_id = models.IntegerField() bookmarkable_type = models.CharField(max_length=255) class Meta: db_table = 'bookmarks' managed = False