class TokenV2(models.Model): """ Device specific token """ key = models.CharField(max_length=40, primary_key=True) user = LowerCaseCharField(max_length=255) # windows/linux/mac/ios/android platform = LowerCaseCharField(max_length=32) # ccnet id, android secure id, etc. device_id = models.CharField(max_length=40) # lin-laptop device_name = models.CharField(max_length=40) # platform version platform_version = LowerCaseCharField(max_length=16) # seafile client/app version client_version = LowerCaseCharField(max_length=16) # most recent activity last_accessed = models.DateTimeField(auto_now=True) last_login_ip = models.GenericIPAddressField(null=True, default=None) objects = TokenV2Manager() class Meta: unique_together = (('user', 'platform', 'device_id'), ) def save(self, *args, **kwargs): if not self.key: self.key = self.generate_key() return super(TokenV2, self).save(*args, **kwargs) def generate_key(self): unique = str(uuid.uuid4()) return hmac.new(unique, digestmod=sha1).hexdigest() def __unicode__(self): return "TokenV2{user=%(user)s,device=%(device_name)s}" % \ dict(user=self.user,device_name=self.device_name) def is_desktop_client(self): return str(self.platform) in ('windows', 'linux', 'mac') def as_dict(self): return dict(key=self.key, user=self.user, platform=self.platform, device_id=self.device_id, device_name=self.device_name, client_version=self.client_version, platform_version=self.platform_version, last_accessed=self.last_accessed, last_login_ip=self.last_login_ip)
class DraftReview(TimestampedModel): creator = LowerCaseCharField(max_length=255, db_index=True) author = LowerCaseCharField(max_length=255, db_index=True) status = models.CharField(max_length=20) origin_repo_id = models.CharField(max_length=36) origin_file_uuid = models.ForeignKey(FileUUIDMap, on_delete=models.CASCADE) draft_file_path = models.CharField(max_length=1024) origin_file_version = models.CharField(max_length=100) publish_file_version = models.CharField(max_length=100, null=True) draft_id = models.OneToOneField(Draft, null=True, on_delete=models.SET_NULL) objects = DraftReviewManager() def to_dict(self): r_repo = seafile_api.get_repo(self.origin_repo_id) if not r_repo: raise DraftFileConflict return { 'id': self.pk, 'creator': self.creator, 'status': self.status, 'creator_name': email2nickname(self.creator), 'draft_origin_repo_id': self.origin_repo_id, 'draft_origin_repo_name': r_repo.name, 'draft_origin_file_version': self.origin_file_version, 'draft_publish_file_version': self.publish_file_version, 'draft_file_path': self.draft_file_path, 'created_at': datetime_to_isoformat_timestr(self.created_at), 'updated_at': datetime_to_isoformat_timestr(self.updated_at), }
class Invitation(models.Model): INVITE_TYPE_CHOICES = ( (GUEST, 'Guest'), ) token = models.CharField(max_length=40, db_index=True) inviter = LowerCaseCharField(max_length=255, db_index=True) accepter = LowerCaseCharField(max_length=255) invite_type = models.CharField(max_length=20, choices=INVITE_TYPE_CHOICES, default=GUEST) invite_time = models.DateTimeField(auto_now_add=True) accept_time = models.DateTimeField(null=True, blank=True) expire_time = models.DateTimeField() objects = InvitationManager() def __unicode__(self): return "Invitation from %s on %s (%s)" % ( self.inviter, self.invite_time, self.token) def accept(self): self.accept_time = timezone.now() self.save() def to_dict(self): accept_time = datetime_to_isoformat_timestr(self.accept_time) \ if self.accept_time else "" return { "id": self.pk, "token": self.token, "inviter": self.inviter, "accepter": self.accepter, "type": self.invite_type, "invite_time": datetime_to_isoformat_timestr(self.invite_time), "accept_time": accept_time, "expire_time": datetime_to_isoformat_timestr(self.expire_time), } def is_guest(self): return self.invite_type == GUEST def is_expired(self): return timezone.now() >= self.expire_time def send_to(self, email=None): """ Send an invitation email to ``email``. """ if not email: email = self.accepter context = self.to_dict() context['site_name'] = get_site_name() subject = _('You are invited to join %(site_name)s.') % {'site_name': get_site_name()} return send_html_email_with_dj_template(email, subject=subject, dj_template='invitations/invitation_email.html', context=context)
class AnonymousShare(models.Model): """ Model used for sharing repo to unregistered email. """ repo_owner = LowerCaseCharField(max_length=255) repo_id = models.CharField(max_length=36) anonymous_email = LowerCaseCharField(max_length=255) token = models.CharField(max_length=25, unique=True)
class PrivateFileDirShare(models.Model): from_user = LowerCaseCharField(max_length=255, db_index=True) to_user = LowerCaseCharField(max_length=255, db_index=True) repo_id = models.CharField(max_length=36, db_index=True) path = models.TextField() token = models.CharField(max_length=10, unique=True) permission = models.CharField(max_length=5) # `r` or `rw` s_type = models.CharField(max_length=5, default='f') # `f` or `d` objects = PrivateFileDirShareManager()
class UserMessage(models.Model): message_id = models.AutoField(primary_key=True) message = models.CharField(max_length=512) from_email = LowerCaseCharField(max_length=255, db_index=True) to_email = LowerCaseCharField(max_length=255, db_index=True) timestamp = models.DateTimeField(default=datetime.datetime.now) ifread = models.BooleanField() objects = UserMessageManager() def __unicode__(self): return "%s|%s|%s" % (self.from_email, self.to_email, self.message)
class Contact(models.Model): """Record user's contacts.""" user_email = LowerCaseCharField(max_length=CONTACT_EMAIL_LENGTH, db_index=True) contact_email = LowerCaseCharField(max_length=CONTACT_EMAIL_LENGTH) contact_name = models.CharField(max_length=255, blank=True, null=True, \ default='') note = models.CharField(max_length=255, blank=True, null=True, default='') objects = ContactManager() def __unicode__(self): return self.contact_email
class DTableShareLinks(models.Model): PERMISSION_CHOICES = ((PERMISSION_READ, 'read only'), (PERMISSION_READ_WRITE, 'read and write')) dtable = models.ForeignKey(DTables, on_delete=models.CASCADE, db_index=True, db_column='dtable_id') username = LowerCaseCharField(max_length=255, db_index=True) token = models.CharField(max_length=100, unique=True) ctime = models.DateTimeField(default=datetime.datetime.now) password = models.CharField(max_length=128, null=True) expire_date = models.DateTimeField(null=True) permission = models.CharField(max_length=50, db_index=True, choices=PERMISSION_CHOICES, default=PERMISSION_READ) objects = DTableShareLinksManager() class Meta: db_table = 'dtable_share_links' def is_owner(self, username): return self.username == username def is_expired(self): if not self.expire_date: return False else: return self.expire_date < timezone.now()
class Migration(migrations.Migration): # dependencies = [ # migrations.swappable_dependency(settings.AUTH_USER_MODEL), # ] operations = [ migrations.CreateModel( name='StaticDevice', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('name', models.CharField(help_text='The human-readable name of this device.', max_length=64)), ('confirmed', models.BooleanField(default=True, help_text='Is this device ready for use?')), # ('user', models.ForeignKey(help_text='The user that this device belongs to.', to=settings.AUTH_USER_MODEL)), ('user', LowerCaseCharField(max_length=255, help_text="The user that this device belongs to.")), ], options={ 'abstract': False, }, bases=(models.Model,), ), migrations.CreateModel( name='StaticToken', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('token', models.CharField(max_length=16, db_index=True)), ('device', models.ForeignKey(related_name='token_set', to='otp_static.StaticDevice')), ], options={ }, bases=(models.Model,), ), ]
class RevisionTags(models.Model): repo_id = models.CharField(max_length=36, db_index=True) path = models.TextField(default='/') revision_id = models.CharField(max_length=255, db_index=True) tag = models.ForeignKey("Tags", on_delete=models.CASCADE) username = LowerCaseCharField(max_length=255, db_index=True) objects = RevisionTagsManager() def to_dict(self): repo = seafile_api.get_repo(self.repo_id) commit = seaserv.get_commit(repo.id, repo.revision, self.revision_id) email = commit.creator_name return { "tag": self.tag.name, "tag_creator": self.username, "revision": { "repo_id": self.repo_id, "commit_id": self.revision_id, "email": email, "name": email2nickname(email), "contact_email": email2contact_email(email), "time": timestamp_to_isoformat_timestr(commit.ctime), "description": commit.desc, "link": reverse("repo_history_view", args=[self.repo_id]) + "?commit_id=%s" % self.revision_id } }
class FileShare(models.Model): """ Model used for file or dir shared link. """ username = LowerCaseCharField(max_length=255, db_index=True) repo_id = models.CharField(max_length=36, db_index=True) path = models.TextField() token = models.CharField(max_length=10, unique=True) ctime = models.DateTimeField(default=datetime.datetime.now) view_cnt = models.IntegerField(default=0) s_type = models.CharField(max_length=2, db_index=True, default='f') # `f` or `d` password = models.CharField(max_length=128, null=True) expire_date = models.DateTimeField(null=True) objects = FileShareManager() def is_file_share_link(self): return True if self.s_type == 'f' else False def is_dir_share_link(self): return False if self.is_file_share_link() else True def is_encrypted(self): return True if self.password is not None else False def is_expired(self): if self.expire_date is not None and timezone.now() > self.expire_date: return True else: return False def is_owner(self, owner): return owner == self.username
class UploadLinkShare(models.Model): """ Model used for shared upload link. """ username = LowerCaseCharField(max_length=255, db_index=True) repo_id = models.CharField(max_length=36, db_index=True) path = models.TextField() token = models.CharField(max_length=100, unique=True) ctime = models.DateTimeField(default=datetime.datetime.now) view_cnt = models.IntegerField(default=0) password = models.CharField(max_length=128, null=True) expire_date = models.DateTimeField(null=True) objects = UploadLinkShareManager() def is_encrypted(self): return True if self.password is not None else False def is_owner(self, owner): return owner == self.username def is_expired(self): if self.expire_date is not None and timezone.now() > self.expire_date: return True else: return False
class Avatar(models.Model, AvatarBase): emailuser = LowerCaseCharField(max_length=255) primary = models.BooleanField(default=False) avatar = models.ImageField(max_length=1024, upload_to=avatar_file_path, storage=get_avatar_file_storage(), blank=True) date_uploaded = models.DateTimeField(default=datetime.datetime.now) def __unicode__(self): return _(u'Avatar for %s') % self.emailuser def save(self, *args, **kwargs): avatars = Avatar.objects.filter(emailuser=self.emailuser) if self.pk: avatars = avatars.exclude(pk=self.pk) if AVATAR_MAX_AVATARS_PER_USER > 1: if self.primary: avatars = avatars.filter(primary=True) avatars.update(primary=False) else: avatars.delete() invalidate_cache(self.emailuser) super(Avatar, self).save(*args, **kwargs) def delete(self, *args, **kwargs): invalidate_cache(self.emailuser) super(Avatar, self).delete(*args, **kwargs)
class Wiki(models.Model): """New wiki model to enable a user has multiple wikis and replace personal wiki. """ PERM_CHOICES = ( ('private', 'private'), ('public', 'public'), ) username = LowerCaseCharField(max_length=255) name = models.CharField(max_length=255) slug = models.CharField(max_length=255, unique=True) repo_id = models.CharField(max_length=36, db_index=True) permission = models.CharField(max_length=50) # private, public created_at = models.DateTimeField(default=timezone.now, db_index=True) objects = WikiManager() class Meta: unique_together = (('username', 'repo_id'), ) ordering = ["name"] @property def link(self): return get_site_scheme_and_netloc().rstrip('/') + reverse( 'wiki:slug', args=[self.slug]) @property def updated_at(self): assert len(self.repo_id) == 36 repo = seafile_api.get_repo(self.repo_id) if not repo: return '' return repo.last_modify def has_read_perm(self, request): from seahub.views import check_folder_permission if self.permission == 'public': return True else: # private if not request.user.is_authenticated(): return False repo_perm = check_folder_permission(request, self.repo_id, '/') if not repo_perm: return False return True def to_dict(self): return { 'id': self.pk, 'owner': self.username, 'owner_nickname': email2nickname(self.username), 'name': self.name, 'slug': self.slug, 'link': self.link, 'permission': self.permission, 'created_at': datetime_to_isoformat_timestr(self.created_at), 'updated_at': timestamp_to_isoformat_timestr(self.updated_at), }
class FileTag(models.Model): uuid = models.ForeignKey(FileUUIDMap, on_delete=models.CASCADE) tag = models.ForeignKey(Tags) username = LowerCaseCharField(max_length=255) objects = FileTagManager() def to_dict(self): return {'id': self.tag.id, 'name': self.tag.name, 'creator': self.username}
class UploadLinkShare(models.Model): """ Model used for shared upload link. """ username = LowerCaseCharField(max_length=255, db_index=True) repo_id = models.CharField(max_length=36, db_index=True) path = models.TextField() token = models.CharField(max_length=10, unique=True) ctime = models.DateTimeField(default=datetime.datetime.now) view_cnt = models.IntegerField(default=0)
class FileShare(models.Model): """ Model used for file or dir shared link. """ username = LowerCaseCharField(max_length=255, db_index=True) repo_id = models.CharField(max_length=36, db_index=True) path = models.TextField() token = models.CharField(max_length=10, unique=True) ctime = models.DateTimeField(default=datetime.datetime.now) view_cnt = models.IntegerField(default=0) s_type = models.CharField(max_length=2, db_index=True, default='f') # `f` or `d`
class DeviceToken(models.Model): """ The iOS device token model. """ token = models.CharField(max_length=80) user = LowerCaseCharField(max_length=255) class Meta: unique_together = (("token", "user"), ) def __unicode__(self): return "/".join(self.user, self.token)
class FileParticipant(models.Model): """ Model used to record file participants. """ uuid = models.ForeignKey(FileUUIDMap, on_delete=models.CASCADE) username = LowerCaseCharField(max_length=255) objects = FileParticipantManager() class Meta: """Meta data""" unique_together = ('uuid', 'username')
class UserTermsAndConditions(models.Model): """Holds mapping between TermsAndConditions and Users""" username = LowerCaseCharField(max_length=255) terms = models.ForeignKey("TermsAndConditions", related_name="userterms") ip_address = models.GenericIPAddressField(null=True, blank=True, verbose_name='IP Address') date_accepted = models.DateTimeField(auto_now_add=True, verbose_name='Date Accepted') class Meta: """Model Meta Information""" get_latest_by = 'date_accepted' verbose_name = 'User Terms and Conditions' verbose_name_plural = 'User Terms and Conditions' unique_together = ('username', 'terms',)
class FileShare(models.Model): """ Model used for file or dir shared link. """ PERM_VIEW_DL = 'view_download' PERM_VIEW_ONLY = 'view_only' PERMISSION_CHOICES = ( (PERM_VIEW_DL, 'View and download'), (PERM_VIEW_ONLY, 'Disable download'), ) username = LowerCaseCharField(max_length=255, db_index=True) repo_id = models.CharField(max_length=36, db_index=True) path = models.TextField() token = models.CharField(max_length=100, unique=True) ctime = models.DateTimeField(default=datetime.datetime.now) view_cnt = models.IntegerField(default=0) s_type = models.CharField(max_length=2, db_index=True, default='f') # `f` or `d` password = models.CharField(max_length=128, null=True) expire_date = models.DateTimeField(null=True) permission = models.CharField(max_length=50, db_index=True, choices=PERMISSION_CHOICES, default=PERM_VIEW_DL) objects = FileShareManager() def is_file_share_link(self): return True if self.s_type == 'f' else False def is_dir_share_link(self): return False if self.is_file_share_link() else True def is_encrypted(self): return True if self.password is not None else False def is_expired(self): if self.expire_date is not None and timezone.now() > self.expire_date: return True else: return False def is_owner(self, owner): return owner == self.username def get_full_url(self): service_url = get_service_url().rstrip('/') if self.is_file_share_link(): return '%s/f/%s/' % (service_url, self.token) else: return '%s/d/%s/' % (service_url, self.token)
class ReviewReviewer(models.Model): """ Model used to record review reviewer. """ reviewer = LowerCaseCharField(max_length=255, db_index=True) review_id = models.ForeignKey('DraftReview', on_delete=models.CASCADE) objects = ReviewReviewerManager() def to_dict(self): return { 'nickname': email2nickname(self.reviewer), 'name': self.reviewer, }
class ProxyGrantingTicket(models.Model): class Meta: unique_together = ('session_key', 'user') session_key = models.CharField(max_length=255, blank=True, null=True) user = LowerCaseCharField(max_length=255, db_index=True) pgtiou = models.CharField(max_length=255, null=True, blank=True) pgt = models.CharField(max_length=255, null=True, blank=True) date = models.DateTimeField(auto_now_add=True) @classmethod def clean_deleted_sessions(cls): for pgt in cls.objects.all(): session = SessionStore(session_key=pgt.session_key) user = get_user_from_session(session) if django.VERSION[0] < 2: if not user.is_authenticated: pgt.delete() else: if not user.is_authenticated: pgt.delete() @classmethod def retrieve_pt(cls, request, service): """`request` should be the current HttpRequest object `service` a string representing the service for witch we want to retrieve a ticket. The function return a Proxy Ticket or raise `ProxyError` """ try: pgt = cls.objects.get(user=request.user.username, session_key=request.session.session_key).pgt except cls.DoesNotExist: raise ProxyError( "INVALID_TICKET", "No proxy ticket found for this HttpRequest object") else: client = get_cas_client(service_url=service, request=request) try: return client.get_proxy_ticket(pgt) # change CASError to ProxyError nicely except CASError as error: raise ProxyError(*error.args) # just embed other errors except Exception as e: raise ProxyError(e)
class Draft(TimestampedModel): """Draft models enable user save file as drafts, and publish later. """ username = LowerCaseCharField(max_length=255, db_index=True) status = models.CharField(max_length=20, default='open') draft_file_path = models.CharField(max_length=1024) origin_repo_id = models.CharField(max_length=36, db_index=True) origin_file_uuid = models.UUIDField(unique=True) origin_file_version = models.CharField(max_length=100) publish_file_version = models.CharField(max_length=100, null=True) objects = DraftManager() # class Meta: # unique_together = (('username', 'draft_repo_id'), ) def update(self, publish_file_version, status='published'): self.publish_file_version = publish_file_version self.status = status self.save() def delete(self, operator): draft_file_name = os.path.basename(self.draft_file_path) draft_file_path = os.path.dirname(self.draft_file_path) seafile_api.del_file(self.origin_repo_id, draft_file_path, draft_file_name, operator) super(Draft, self).delete() def to_dict(self): uuid = FileUUIDMap.objects.get_fileuuidmap_by_uuid( self.origin_file_uuid) file_path = posixpath.join(uuid.parent_path, uuid.filename) return { 'id': self.pk, 'owner': self.username, 'owner_nickname': email2nickname(self.username), 'origin_repo_id': self.origin_repo_id, 'origin_file_path': file_path, 'origin_file_version': self.origin_file_version, 'draft_file_path': self.draft_file_path, 'created_at': datetime_to_isoformat_timestr(self.created_at), 'updated_at': datetime_to_isoformat_timestr(self.updated_at), }
class Token(models.Model): """ The default authorization token model. """ key = models.CharField(max_length=40, primary_key=True) user = LowerCaseCharField(max_length=255, unique=True) created = models.DateTimeField(auto_now_add=True) def save(self, *args, **kwargs): if not self.key: self.key = self.generate_key() return super(Token, self).save(*args, **kwargs) def generate_key(self): unique = str(uuid.uuid4()) return hmac.new(unique, digestmod=sha1).hexdigest() def __unicode__(self): return self.key
class FileShare(models.Model): """ Model used for file or dir shared link. """ username = LowerCaseCharField(max_length=255, db_index=True) repo_id = models.CharField(max_length=36, db_index=True) path = models.TextField() token = models.CharField(max_length=10, unique=True) ctime = models.DateTimeField(default=datetime.datetime.now) view_cnt = models.IntegerField(default=0) s_type = models.CharField(max_length=2, db_index=True, default='f') # `f` or `d` objects = FileShareManager() def is_file_share_link(self): return True if self.s_type == 'f' else False def is_dir_share_link(self): return False if self.is_file_link() else True
class ReviewComment(TimestampedModel): """ Model used to record file comments. """ author = LowerCaseCharField(max_length=255, db_index=True) resolved = models.BooleanField(default=False, db_index=True) review_id = models.ForeignKey('DraftReview', on_delete=models.CASCADE) comment = models.TextField() detail = models.TextField() objects = ReviewCommentManager() def to_dict(self): return { 'id': self.pk, 'review_id': self.review_id_id, 'comment': self.comment, 'created_at': datetime_to_isoformat_timestr(self.created_at), 'updated_at': datetime_to_isoformat_timestr(self.updated_at), 'resolved': self.resolved, 'detail': self.detail, }
class UploadLinkShare(models.Model): """ Model used for shared upload link. """ username = LowerCaseCharField(max_length=255, db_index=True) repo_id = models.CharField(max_length=36, db_index=True) path = models.TextField() token = models.CharField(max_length=100, unique=True) ctime = models.DateTimeField(default=datetime.datetime.now) view_cnt = models.IntegerField(default=0) password = models.CharField(max_length=128, null=True) expire_date = models.DateTimeField(null=True) objects = UploadLinkShareManager() def is_encrypted(self): return True if self.password is not None else False def is_owner(self, owner): return owner == self.username def is_expired(self): if self.expire_date is not None and timezone.now() > self.expire_date: return True else: return False def get_password(self): if self.password: try: aes = AESPasswordHasher() return aes.decode(self.password) except Exception: logger.error('Error occurred when get share link password') return '' else: return ''
class MessageReply(models.Model): reply_to = models.ForeignKey(GroupMessage) from_email = LowerCaseCharField(max_length=255) message = models.TextField() timestamp = models.DateTimeField(default=datetime.datetime.now)
class GroupMessage(models.Model): group_id = models.IntegerField(db_index=True) from_email = LowerCaseCharField(max_length=255) message = models.TextField() timestamp = models.DateTimeField(default=datetime.datetime.now)