Example #1
0
class ProjectGroupLimitFactors(object):

    # project_group billing-type에 따라 count에 제한을 둠.
    da_cnt_limit = db.IntField(default=100)
    project_cnt_limit = db.IntField(default=100)
    member_cnt_limit = db.IntField(default=100)

    # project 생성통제
    ban_create_project = db.BooleanField(default=False)

    # ip기반의 위치통제를 하기 위함
    use_firewall = db.BooleanField(default=False)
    firewall_rules = db.ListField(db.EmbeddedDocumentField(FirewallRule))

    def check_allowed_ip(self, ipaddr_str):
        ipaddr = ipaddress.ip_address(text(ipaddr_str))
        rules = [rule for rule in self.firewall_rules if rule.allow]

        if len(rules) == 0:
            return True

        return any((rule.match(ipaddr) for rule in rules))

    def is_firewall_working(self):
        return self.use_firewall and len(self.firewall_rules) > 0
Example #2
0
class FirewallRule(db.EmbeddedDocument):

    seq = db.IntField(default=0)
    allow = db.BooleanField(default=True)
    source = db.StringField(max_length=50, required=True)
    cidr = db.IntField(max_value=32, required=True)

    def to_ipcidr(self):
        return u"{0}/{1}".format(self.source, self.cidr)

    def match(self, ipaddr):
        # if isinstance(ipaddr, str) or isinstance(ipaddr, unicode):
        if isinstance(ipaddr, six.text_type):
            ipaddr = ipaddress.ip_address(text(ipaddr))
        return ipaddr in ipaddress.ip_network(self.to_ipcidr())
Example #3
0
class ProjectGroupNotice(db.EmbeddedDocument):
    # project_group = db.ReferenceField('ProjectGroup')
    seq = db.IntField(default=0)
    created_at = db.DateTimeField(default=datetime.now, required=True)
    created_by = db.ReferenceField('User', required=True)
    publish_begin_at = db.DateTimeField(default=datetime.now, required=True)
    publish_end_at = db.DateTimeField(default=datetime.now, required=True)
    content = db.StringField(required=True)
Example #4
0
class ProjectRecommendationMixin(object):
    """프로젝트 추천하기."""

    picked = db.BooleanField(default=False)
    display_priority = db.IntField(default=0)

    @classmethod
    def _random(cls, limit, project_group, picked=False):
        u"""추천알고리즘없이 임의로 프로젝트 골라오기."""
        kw = dict(private=False,
                  visible=True,
                  demo=False,
                  project_group=project_group)
        if picked:
            kw['picked'] = True  # picked는 false일때는 true/false모두 챙긴다.

        projects = Project.objects(**kw).no_dereference().only('id')
        if len(projects):
            random.shuffle(list(projects))
            projects = [
                projects[i].reload() for i in range(min(limit, len(projects)))
            ]
            projects.sort(key=lambda x: -x.display_priority)
            return projects
        else:
            return []

    @classmethod
    def random(cls, limit=4, project_group=None):
        """추천알고리즘없이 임의로 프로젝트 골라오기.

        PROJECT:
        이 함수들은 성능이 좋지 않아서 PRODUCTION에서는 사용할 수 없습니다.
        batch로 project list를 준비하던가 해야겠음

        """
        if project_group is None:
            project_group = ProjectGroup.default()

        # picked priority
        selected = cls._random(limit=limit,
                               picked=True,
                               project_group=project_group)

        if len(selected) < limit:
            # 만약 limit만큼 채워지지 않았으면 조금 더 얻어오기
            chunks = cls._random(limit=limit - len(selected),
                                 project_group=project_group)
            selected.extend(chunks)

        # shuffle!
        # random.shuffle(selected)
        return selected
Example #5
0
class ProjectWaitingUserOutbound(ProjectUserBase):
    """가입되지 않은 사용자를 초대받을때"""
    user = db.EmailField(required=True)
    outbound_email_sent_at = db.DateTimeField()
    outbound_email_sent_count = db.IntField(default=0)
    invited_by = db.ReferenceField('User',
                                   reverse_delete_rule=mongoengine.NULLIFY)
    invited_at = db.DateTimeField(default=datetime.now)
    # dropped = db.BooleanField(default=False)

    render_template_path = 'project/_members_invited_tbl_row.html'

    @property
    def is_expired(self):
        '''초대요청이 오래지나면 만료된다. 만료기간은 14일.'''
        return self.outbound_email_sent_at < datetime.now() - \
            timedelta(days=14)

    def check_integrity(self):
        '''외부사용자객체의 무결성을 검사합니다.
        외부사용자로 되어있는데 실제 user에도 존재하는 경우는 강제보정
        만료된 객체의 경우 삭제처리합니다.'''

        if self.is_expired:
            logger.info(
                'Deleting expired old-waiting-user-project-relation'
                '[%s].', self)
            self.delete()
        else:
            user = User.objects(email=self.user).first()
            if user:
                '''이미 가입된 사용자로 존재하는군요.
                프로젝트와의 관계까지검사합니다.'''
                relation = ProjectUserBase.objects(project=self.project,
                                                   user=user).first()
                if relation:
                    logger.info(
                        'Deleting useless old-waiting-user-project-relation'
                        '[%s].', self)
                    self.delete()  # useless.
                else:
                    '''미처리된 사용자이므로 가입처리'''
                    new_project_user = ProjectUser(project=self.project,
                                                   user=user).save()
                    logger.info('Creating new-user-project-relation'
                                '[%s].', new_project_user)
                    logger.info(
                        'Deleting old-waiting-user-project-relation'
                        '[%s].', self)
                    self.delete()
            else:
                '''정상적인 waiting이므로 done nothing.'''
                pass

    def sendmail(self):
        if self.outbound_email_sent_count > 4:
            logger.warning('outbound-email[%s]-surge-protection', self.user)
            return

        token = InviteToken(email=self.user, project=self.project).save()
        token.sendmail()

        self.outbound_email_sent_at = datetime.now()
        self.outbound_email_sent_count += 1
        self.save()

    def clean(self):
        if self.project.project_group.is_not_default:
            raise ValidationError(
                'outbound-user cannot be created at non-default-project-group')

        # 초대그룹의 email이 encrypt되어있지 않아서 다른쪽과 interface를 맞추기 위해 암호화
        self.user_email = self.user

    def to_json(self, *args, **kwargs):
        """일부 계산된 properties를 json으로 내보내기 위한 patch"""
        ret = super(ProjectWaitingUserOutbound, self).to_json(*args, **kwargs)

        # patch for email-encryption (slow...)
        from json import dumps, loads
        d = loads(ret)
        d['is_expired'] = self.is_expired
        return dumps(d)