class IssueMilestone(OrzBase): __orz_table__ = "issue_milestones" issue_id = OrzField(as_key=True) milestone_id = OrzField(as_key=True) creator_id = OrzField() created_at = OrzField(default='null') class OrzMeta: id2str = True @property def milestone(self): return Milestone.get_by(self.milestone_id) @classmethod def get_by_issue(cls, issue): rs = cls.gets_by(issue_id=issue.issue_id) r = rs[0] if rs else None return r @classmethod def create_by_issue(cls, issue, milestone, user): ims = cls.create(issue_id=issue.issue_id, milestone_id=milestone.id, creator_id=user.name, created_at=datetime.now()) return ims
class TeamProject(OrzBase): __orz_table__ = "team_projects" team_id = OrzField(as_key=True) project_id = OrzField() created_at = OrzField(default='null') @property def project(self): return CodeDoubanProject.get(self.project_id)
class ProjectFork(OrzBase): __orz_table__ = "project_forks" project_id = OrzField(as_key=OrzField.KeyType.DESC) forked_id = OrzField(as_key=OrzField.KeyType.DESC) family_id = OrzField(as_key=OrzField.KeyType.DESC) creator_id = OrzField(as_key=OrzField.KeyType.DESC) created_at = OrzField() class OrzMeta: id2str = True
class Organization(OrzBase): __orz_table__ = "organizations" name = OrzField(as_key=OrzField.KeyType.DESC) description = OrzField() owner_id = OrzField(as_key=OrzField.KeyType.DESC) creator_id = OrzField(as_key=OrzField.KeyType.DESC) created_at = OrzField(default='null') updated_at = OrzField(default='null') class OrzMeta: id2str = True @classmethod def get_by_name(cls, name): rs = cls.gets_by(name=name) return rs[0] if rs else None @classmethod def add(cls, **kw): now = datetime.now() kw['created_at'] = now kw['updated_at'] = now p = None try: p = cls.create(**kw) except IntegrityError: store.rollback() return p
class Team(OrzBase, PropsMixin, TagMixin): __orz_table__ = "team" team_id = OrzField(as_key=OrzField.KeyType.DESC) name = OrzField(as_key=OrzField.KeyType.DESC) description = OrzField(default='') created_at = OrzField(default='null') @property def uid(self): # TODO: change uid to name return self.team_id @property def title(self): return self.name def __repr__(self): return '<Team %s, %s>' % (self.id, self.uid) def __str__(self): return self.name def get_uuid(self): return "/team/%s" % self.id uuid = property(get_uuid) profile = PropsItem("profile", {}) weekly = PropsItem("weekly") def profile_url(self): if not self.profile: return "/static/img/team_default_profile.jpg" else: return self.profile.get('origin') @property def tag_type(self): return TAG_TYPE_TEAM_ISSUE @property def url(self): return '/teams/%s/' % self.uid @property def doc_project(self): team_projects = TeamProject.gets_by(team_id=self.id) if not team_projects: return None team_project = team_projects[0] return team_project.project @property def members(self): pass @property def owners(self): pass @property def projects(self): from vilya.models.project import CodeDoubanProject return filter(None, [CodeDoubanProject.get(_) for _ in self.project_ids]) def as_dict(self): d = {} d['name'] = self.name d['description'] = self.description d['uid'] = self.uid d['created_at'] = self.created_at.strftime('%Y-%m-%dT%H:%M:%S') return d
class Milestone(OrzBase): __orz_table__ = "milestones" name = OrzField(as_key=OrzField.KeyType.DESC) creator_id = OrzField() target_id = OrzField(as_key=OrzField.KeyType.DESC) target_type = OrzField(as_key=OrzField.KeyType.DESC) target_number = OrzField(as_key=OrzField.KeyType.DESC) created_at = OrzField(default='null') class OrzMeta: id2str = True # FIXME: ugly wrapper @classmethod def create_by_project(cls, project, name, user): target_number = MTCounter.incr(project.id, PROJECT_MILESTONE_TYPE) try: ms = cls.create(name=name, target_id=project.id, target_type=PROJECT_MILESTONE_TYPE, target_number=target_number, creator_id=user.name, created_at=datetime.now()) except IntegrityError: store.rollback() rs = cls.gets_by(target_id=project.id, target_type=PROJECT_MILESTONE_TYPE, target_number=target_number) ms = rs[0] ms.name = name ms.save() return ms # FIXME: ugly wrapper @classmethod def gets_by_project(cls, project, number=None, name=None): if name: rs = cls.gets_by(name=name, target_id=project.id, target_type=PROJECT_MILESTONE_TYPE) elif number: rs = cls.gets_by(target_id=project.id, target_type=PROJECT_MILESTONE_TYPE, target_number=number) else: rs = cls.gets_by(target_id=project.id, target_type=PROJECT_MILESTONE_TYPE) return rs # FIXME: ugly wrapper @classmethod def get_by_project(cls, project, number=None, name=None): rs = cls.gets_by_project(project, number=number, name=name) return rs[0] if rs else None @property def tasks(self): from vilya.models.milestone_task import MilestoneTask return MilestoneTask(self).get_multi() @property def issue_ids(self): from vilya.models.milestone_task import MilestoneTask # TODO: check milestone type ms = MilestoneTask(self).get_multi() # TODO: orz return int return [int(m.issue_id) for m in ms] @property def open_tasks(self): from vilya.models.milestone_task import MilestoneTask return MilestoneTask(self).get_multi(state="open") @property def closed_tasks(self): from vilya.models.milestone_task import MilestoneTask return MilestoneTask(self).get_multi(state="closed") @property def percentage(self): closed_count = self.closed_task_count count = self.task_count return closed_count / count * 100 if count else 0 @property def percentage_number(self): number = str(self.percentage) number = number.split('.')[0] return number @property def open_task_count(self): return len(self.open_tasks) @property def closed_task_count(self): return len(self.closed_tasks) @property def task_count(self): return len(self.tasks)
class User(OrzBase, SessionMixin): __orz_table__ = "users" name = OrzField(as_key=OrzField.KeyType.ONLY_INDEX) password = OrzField() description = OrzField() email = OrzField(as_key=OrzField.KeyType.ONLY_INDEX) session_id = OrzField() session_expired_at = OrzField() created_at = OrzField() updated_at = OrzField() class OrzMeta: id2str = True @classmethod def get_by_name(cls, name): rs = cls.gets_by(name=name) return rs[0] if rs else None @classmethod def add(cls, **kw): now = datetime.now() kw['created_at'] = now kw['updated_at'] = now kw['password'] = cls.hash_password(kw['password']) u = None try: u = cls.create(**kw) except IntegrityError: store.rollback() return u # password @property def hashed_password(self): return self.password @hashed_password.setter def _set_password(self, password): self.password = self.hash_password(password) def validate_password(self, password): """Check the password against existing credentials.""" hashed_pass = sha1() hashed_pass.update(password + self.hashed_password[:40]) return self.hashed_password[40:] == hashed_pass.hexdigest() @classmethod def hash_password(cls, password): """Hash password on the fly.""" hashed_password = password if isinstance(password, unicode): password_8bit = password.encode('UTF-8') else: password_8bit = password salt = sha1() salt.update(os.urandom(60)) hash = sha1() hash.update(password_8bit + salt.hexdigest()) hashed_password = salt.hexdigest() + hash.hexdigest() if not isinstance(hashed_password, unicode): hashed_password = hashed_password.decode('UTF-8') return hashed_password @property def projects(self): from vilya.models.project import Project return Project.gets_by(owner_id=self.id)
class Project(OrzBase): __orz_table__ = "projects" name = OrzField(as_key=OrzField.KeyType.DESC) description = OrzField(default='') kind = OrzField(as_key=OrzField.KeyType.DESC, default=KIND_USER) owner_id = OrzField(as_key=OrzField.KeyType.DESC) creator_id = OrzField(as_key=OrzField.KeyType.DESC) created_at = OrzField() updated_at = OrzField() @classmethod def get_by_name(cls, name): rs = cls.gets_by(name=name) return rs[0] if rs else None @classmethod def get_by_name_and_owner(cls, name, owner_id): rs = cls.gets_by(name=name, owner_id=owner_id) return rs[0] if rs else None @classmethod def add(cls, **kw): now = datetime.now() kw['created_at'] = now kw['updated_at'] = now p = None try: p = cls.create(**kw) except IntegrityError: store.rollback() else: p.init_repo() return p ## git wrap @property def repo_http_url(self): # FIXME: use project name return "%s%s.git" % (DOMAIN, self.repo_name) @property def repo_path(self): return os.path.join(get_repo_root(), '%s.git' % self.id) @property def repo_name(self): owner_name = self.owner_name if owner_name: return '%s/%s' % (owner_name, self.name) return "%s" % self.id @property def owner_name(self): from vilya.models.user import User from vilya.models.organization import Organization if self.kind == KIND_USER: user = User.get_by(id=self.owner_id) return user.name else: org = Organization.get_by(id=self.owner_id) return org.name # repository def init_repo(self): from vilya.config import HOOKS_DIR repo = ProjectRepo.init(self.repo_path) repo.update_hooks(HOOKS_DIR) return repo @property def repo(self): return ProjectRepo(self) @property def repo_tree(self): path = '' ref = 'HEAD' tree = self.repo.get_tree(ref, path=path) return tree def as_dict(self): d = dict(id=self.id, name=self.name, full_name=self.repo_name, description=self.description, owner_name=self.owner_name, owner_id=self.owner_id) return d