class UserGrantedMappingNode(FamilyMixin, models.JMSBaseModel): node = models.ForeignKey('assets.Node', default=None, on_delete=models.CASCADE, db_constraint=False, null=True, related_name='mapping_nodes') key = models.CharField(max_length=64, verbose_name=_("Key"), db_index=True) # '1:1:1:1' user = models.ForeignKey('users.User', db_constraint=False, on_delete=models.CASCADE) granted = models.BooleanField(default=False, db_index=True) asset_granted = models.BooleanField(default=False, db_index=True) parent_key = models.CharField(max_length=64, default='', verbose_name=_('Parent key'), db_index=True) # '1:1:1:1' assets_amount = models.IntegerField(default=0) GRANTED_DIRECT = 1 GRANTED_INDIRECT = 2 GRANTED_NONE = 0 @classmethod def get_node_granted_status(cls, key, user): ancestor_keys = Node.get_node_ancestor_keys(key, with_self=True) has_granted = UserGrantedMappingNode.objects.filter( key__in=ancestor_keys, user=user ).values_list('granted', flat=True) if not has_granted: return cls.GRANTED_NONE if any(list(has_granted)): return cls.GRANTED_DIRECT return cls.GRANTED_INDIRECT
class AccessKey(models.Model): id = models.UUIDField(verbose_name='AccessKeyID', primary_key=True, default=uuid.uuid4, editable=False) secret = models.UUIDField(verbose_name='AccessKeySecret', default=uuid.uuid4, editable=False) user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='User', on_delete=models.CASCADE, related_name='access_keys') is_active = models.BooleanField(default=True, verbose_name=_('Active')) date_created = models.DateTimeField(auto_now_add=True) def get_id(self): return str(self.id) def get_secret(self): return str(self.secret) def get_full_value(self): return '{}:{}'.format(self.id, self.secret) def __str__(self): return str(self.id) class Meta: verbose_name = _("Access key")
class SSOToken(models.JMSBaseModel): """ 类似腾讯企业邮的 [单点登录](https://exmail.qq.com/qy_mng_logic/doc#10036) 出于安全考虑,这里的 `token` 使用一次随即过期。但我们保留每一个生成过的 `token`。 """ authkey = models.UUIDField(primary_key=True, default=uuid.uuid4, verbose_name=_('Token')) expired = models.BooleanField(default=False, verbose_name=_('Expired')) user = models.ForeignKey('users.User', on_delete=models.PROTECT, verbose_name=_('User'), db_constraint=False)
class LoginConfirmSetting(CommonModelMixin): user = models.OneToOneField('users.User', on_delete=models.CASCADE, verbose_name=_("User"), related_name="login_confirm_setting") reviewers = models.ManyToManyField( 'users.User', verbose_name=_("Reviewers"), related_name="review_login_confirm_settings", blank=True) is_active = models.BooleanField(default=True, verbose_name=_("Is active")) class Meta: verbose_name = _('Login Confirm') @classmethod def get_user_confirm_setting(cls, user): return get_object_or_none(cls, user=user) @staticmethod def construct_confirm_ticket_meta(request=None): if request: login_ip = get_request_ip(request) else: login_ip = '' login_ip = login_ip or '0.0.0.0' login_city = get_ip_city(login_ip) login_datetime = timezone.now().strftime('%Y-%m-%d %H:%M:%S') ticket_meta = { 'apply_login_ip': login_ip, 'apply_login_city': login_city, 'apply_login_datetime': login_datetime, } return ticket_meta def create_confirm_ticket(self, request=None): from tickets import const from tickets.models import Ticket from orgs.models import Organization ticket_title = _('Login confirm') + ' {}'.format(self.user) ticket_meta = self.construct_confirm_ticket_meta(request) data = { 'title': ticket_title, 'type': const.TicketType.login_confirm.value, 'meta': ticket_meta, 'org_id': Organization.ROOT_ID, } ticket = Ticket.objects.create(**data) ticket.create_process_map_and_node(self.reviewers.all()) ticket.open(self.user) return ticket def __str__(self): reviewers = [u.username for u in self.reviewers.all()] return _('{} need confirm by {}').format(self.user.username, reviewers)
class LoginConfirmSetting(CommonModelMixin): user = models.OneToOneField('users.User', on_delete=models.CASCADE, verbose_name=_("User"), related_name="login_confirm_setting") reviewers = models.ManyToManyField( 'users.User', verbose_name=_("Reviewers"), related_name="review_login_confirm_settings", blank=True) is_active = models.BooleanField(default=True, verbose_name=_("Is active")) @classmethod def get_user_confirm_setting(cls, user): return get_object_or_none(cls, user=user) def create_confirm_ticket(self, request=None): from tickets.models import Ticket title = _('Login confirm') + ' {}'.format(self.user) if request: remote_addr = get_request_ip(request) city = get_ip_city(remote_addr) datetime = timezone.now().strftime('%Y-%m-%d %H:%M:%S') body = __("{user_key}: {username}<br>" "IP: {ip}<br>" "{city_key}: {city}<br>" "{date_key}: {date}<br>").format(user_key=__("User"), username=self.user, ip=remote_addr, city_key=_("City"), city=city, date_key=__("Datetime"), date=datetime) else: body = '' reviewer = self.reviewers.all() ticket = Ticket.objects.create( user=self.user, title=title, body=body, type=Ticket.TYPE.LOGIN_CONFIRM, ) ticket.assignees.set(reviewer) return ticket def __str__(self): return '{} confirm'.format(self.user.username)
class LoginConfirmSetting(CommonModelMixin): user = models.OneToOneField('users.User', on_delete=models.CASCADE, verbose_name=_("User"), related_name="login_confirm_setting") reviewers = models.ManyToManyField('users.User', verbose_name=_("Reviewers"), related_name="review_login_confirm_settings", blank=True) is_active = models.BooleanField(default=True, verbose_name=_("Is active")) @classmethod def get_user_confirm_setting(cls, user): return get_object_or_none(cls, user=user) @staticmethod def construct_confirm_ticket_meta(request=None): if request: login_ip = get_request_ip(request) else: login_ip = '' login_ip = login_ip or '0.0.0.0' login_city = get_ip_city(login_ip) login_datetime = timezone.now().strftime('%Y-%m-%d %H:%M:%S') ticket_meta = { 'apply_login_ip': login_ip, 'apply_login_city': login_city, 'apply_login_datetime': login_datetime, } return ticket_meta def create_confirm_ticket(self, request=None): from tickets import const from tickets.models import Ticket ticket_title = _('Login confirm') + ' {}'.format(self.user) ticket_applicant = self.user ticket_meta = self.construct_confirm_ticket_meta(request) ticket_assignees = self.reviewers.all() data = { 'title': ticket_title, 'type': const.TicketTypeChoices.login_confirm.value, 'applicant': ticket_applicant, 'meta': ticket_meta, } ticket = Ticket.objects.create(**data) ticket.assignees.set(ticket_assignees) return ticket def __str__(self): return '{} confirm'.format(self.user.username)
class TempToken(models.JMSModel): username = models.CharField(max_length=128, verbose_name=_("Username")) secret = models.CharField(max_length=64, verbose_name=_("Secret")) verified = models.BooleanField(default=False, verbose_name=_("Verified")) date_verified = models.DateTimeField(null=True, verbose_name=_("Date verified")) date_expired = models.DateTimeField(verbose_name=_("Date expired")) class Meta: verbose_name = _("Temporary token") @property def user(self): from users.models import User return User.objects.filter(username=self.username).first() @property def is_valid(self): not_expired = self.date_expired and self.date_expired > timezone.now() return not self.verified and not_expired