def create(self): users_group_form = UserGroupForm()() try: form_result = users_group_form.to_python(dict(request.POST)) ug = UserGroupModel().create( name=form_result['users_group_name'], description=form_result['user_group_description'], owner=request.authuser.user_id, active=form_result['users_group_active']) gr = form_result['users_group_name'] action_logger(request.authuser, 'admin_created_users_group:%s' % gr, None, request.ip_addr) h.flash( h.HTML(_('Created user group %s')) % h.link_to(gr, url('edit_users_group', id=ug.users_group_id)), category='success') Session().commit() except formencode.Invalid as errors: return htmlfill.render( render('admin/user_groups/user_group_add.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8", force_defaults=False) except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred during creation of user group %s') % request.POST.get('users_group_name'), category='error') raise HTTPFound(location=url('users_groups'))
def log_pull_action(ui, repo, **kwargs): """ Logs user last pull action :param ui: :param repo: """ ex = _extract_extras() user = User.get_by_username(ex.username) action = 'pull' action_logger(user, action, ex.repository, ex.ip, commit=True) # extension hook call from kallithea import EXTENSIONS callback = getattr(EXTENSIONS, 'PULL_HOOK', None) if callable(callback): kw = {} kw.update(ex) callback(**kw) if ex.make_lock is not None and ex.make_lock: Repository.lock(Repository.get_by_repo_name(ex.repository), user.user_id) #msg = 'Made lock on repo `%s`' % repository #sys.stdout.write(msg) if ex.locked_by[0]: locked_by = User.get(ex.locked_by[0]).username _http_ret = HTTPLockedRC(ex.repository, locked_by) if str(_http_ret.code).startswith('2'): #2xx Codes don't raise exceptions sys.stdout.write(_http_ret.title) return 0
def create(self): """POST /users: Create a new item""" # url('users') c.default_extern_type = auth_internal.KallitheaAuthPlugin.name c.default_extern_name = auth_internal.KallitheaAuthPlugin.name user_model = UserModel() user_form = UserForm()() try: form_result = user_form.to_python(dict(request.POST)) user = user_model.create(form_result) usr = form_result['username'] action_logger(self.authuser, 'admin_created_user:%s' % usr, None, self.ip_addr, self.sa) h.flash(h.literal(_('Created user %s') % h.link_to(h.escape(usr), url('edit_user', id=user.user_id))), category='success') Session().commit() except formencode.Invalid as errors: return htmlfill.render( render('admin/users/user_add.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8", force_defaults=False) except UserCreationError as e: h.flash(e, 'error') except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred during creation of user %s') \ % request.POST.get('username'), category='error') raise HTTPFound(location=url('users'))
def delete(self, repo_name): repo_model = RepoModel() repo = repo_model.get_by_repo_name(repo_name) if not repo: h.not_mapped_error(repo_name) raise HTTPFound(location=url('repos')) try: _forks = repo.forks.count() handle_forks = None if _forks and request.POST.get('forks'): do = request.POST['forks'] if do == 'detach_forks': handle_forks = 'detach' h.flash(_('Detached %s forks') % _forks, category='success') elif do == 'delete_forks': handle_forks = 'delete' h.flash(_('Deleted %s forks') % _forks, category='success') repo_model.delete(repo, forks=handle_forks) action_logger(request.authuser, 'admin_deleted_repo', repo_name, request.ip_addr) ScmModel().mark_for_invalidation(repo_name) h.flash(_('Deleted repository %s') % repo_name, category='success') Session().commit() except AttachedForksError: h.flash(_('Cannot delete repository %s which still has forks') % repo_name, category='warning') except Exception: log.error(traceback.format_exc()) h.flash(_('An error occurred during deletion of %s') % repo_name, category='error') if repo.group: raise HTTPFound(location=url('repos_group_home', group_name=repo.group.group_name)) raise HTTPFound(location=url('repos'))
def create(self): """POST /users_groups: Create a new item""" # url('users_groups') users_group_form = UserGroupForm()() try: form_result = users_group_form.to_python(dict(request.POST)) ug = UserGroupModel().create( name=form_result['users_group_name'], description=form_result['user_group_description'], owner=self.authuser.user_id, active=form_result['users_group_active']) gr = form_result['users_group_name'] action_logger(self.authuser, 'admin_created_users_group:%s' % gr, None, self.ip_addr, self.sa) h.flash(h.literal( _('Created user group %s') % h.link_to(h.escape(gr), url('edit_users_group', id=ug.users_group_id))), category='success') Session().commit() except formencode.Invalid, errors: return htmlfill.render( render('admin/user_groups/user_group_add.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8", force_defaults=False)
def create(self): """POST /users_groups: Create a new item""" # url('users_groups') users_group_form = UserGroupForm()() try: form_result = users_group_form.to_python(dict(request.POST)) ug = UserGroupModel().create(name=form_result['users_group_name'], description=form_result['user_group_description'], owner=self.authuser.user_id, active=form_result['users_group_active']) gr = form_result['users_group_name'] action_logger(self.authuser, 'admin_created_users_group:%s' % gr, None, self.ip_addr, self.sa) h.flash(h.literal(_('Created user group %s') % h.link_to(h.escape(gr), url('edit_users_group', id=ug.users_group_id))), category='success') Session().commit() except formencode.Invalid, errors: return htmlfill.render( render('admin/user_groups/user_group_add.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8", force_defaults=False)
def toggle_following_repo(self, follow_repo_id, user_id): f = self.sa.query(UserFollowing)\ .filter(UserFollowing.follows_repo_id == follow_repo_id)\ .filter(UserFollowing.user_id == user_id).scalar() if f is not None: try: self.sa.delete(f) action_logger(UserTemp(user_id), 'stopped_following_repo', RepoTemp(follow_repo_id)) return except Exception: log.error(traceback.format_exc()) raise try: f = UserFollowing() f.user_id = user_id f.follows_repo_id = follow_repo_id self.sa.add(f) action_logger(UserTemp(user_id), 'started_following_repo', RepoTemp(follow_repo_id)) except Exception: log.error(traceback.format_exc()) raise
def create(self): c.default_extern_type = User.DEFAULT_AUTH_TYPE c.default_extern_name = '' user_model = UserModel() user_form = UserForm()() try: form_result = user_form.to_python(dict(request.POST)) user = user_model.create(form_result) action_logger(request.authuser, 'admin_created_user:%s' % user.username, None, request.ip_addr) h.flash(_('Created user %s') % user.username, category='success') Session().commit() except formencode.Invalid as errors: return htmlfill.render( render('admin/users/user_add.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8", force_defaults=False) except UserCreationError as e: h.flash(e, 'error') except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred during creation of user %s') \ % request.POST.get('username'), category='error') raise HTTPFound(location=url('edit_user', id=user.user_id))
def create(self): users_group_form = UserGroupForm()() try: form_result = users_group_form.to_python(dict(request.POST)) ug = UserGroupModel().create(name=form_result['users_group_name'], description=form_result['user_group_description'], owner=request.authuser.user_id, active=form_result['users_group_active']) gr = form_result['users_group_name'] action_logger(request.authuser, 'admin_created_users_group:%s' % gr, None, request.ip_addr) h.flash(h.literal(_('Created user group %s') % h.link_to(h.escape(gr), url('edit_users_group', id=ug.users_group_id))), category='success') Session().commit() except formencode.Invalid as errors: return htmlfill.render( render('admin/user_groups/user_group_add.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8", force_defaults=False) except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred during creation of user group %s') \ % request.POST.get('users_group_name'), category='error') raise HTTPFound(location=url('users_groups'))
def log_pull_action(ui, repo, **kwargs): """ Logs user last pull action :param ui: :param repo: """ ex = _extract_extras() user = User.get_by_username(ex.username) action = 'pull' action_logger(user, action, ex.repository, ex.ip, commit=True) # extension hook call from kallithea import EXTENSIONS callback = getattr(EXTENSIONS, 'PULL_HOOK', None) if callable(callback): kw = {} kw.update(ex) callback(**kw) if ex.make_lock is not None and ex.make_lock: Repository.lock(Repository.get_by_repo_name(ex.repository), user.user_id) #msg = 'Made lock on repo `%s`' % repository #ui.status(msg) if ex.locked_by[0]: locked_by = User.get(ex.locked_by[0]).username _http_ret = HTTPLockedRC(ex.repository, locked_by) if str(_http_ret.code).startswith('2'): #2xx Codes don't raise exceptions ui.status(safe_str(_http_ret.title)) return 0
def toggle_following_repo(self, follow_repo_id, user_id): f = UserFollowing.query() \ .filter(UserFollowing.follows_repository_id == follow_repo_id) \ .filter(UserFollowing.user_id == user_id).scalar() if f is not None: try: Session().delete(f) action_logger(UserTemp(user_id), 'stopped_following_repo', RepoTemp(follow_repo_id)) return except Exception: log.error(traceback.format_exc()) raise try: f = UserFollowing() f.user_id = user_id f.follows_repository_id = follow_repo_id Session().add(f) action_logger(UserTemp(user_id), 'started_following_repo', RepoTemp(follow_repo_id)) except Exception: log.error(traceback.format_exc()) raise
def comment(self, repo_name, revision): status = request.POST.get('changeset_status') text = request.POST.get('text', '').strip() or _('No comments.') c.co = comm = ChangesetCommentsModel().create( text=text, repo=c.db_repo.repo_id, user=c.authuser.user_id, revision=revision, f_path=request.POST.get('f_path'), line_no=request.POST.get('line'), status_change=(ChangesetStatus.get_status_lbl(status) if status else None)) # get status if set ! if status: # if latest status was from pull request and it's closed # disallow changing status ! # dont_allow_on_closed_pull_request = True ! try: ChangesetStatusModel().set_status( c.db_repo.repo_id, status, c.authuser.user_id, comm, revision=revision, dont_allow_on_closed_pull_request=True) except StatusChangeOnClosedPullRequestError: log.error(traceback.format_exc()) msg = _('Changing status on a changeset associated with ' 'a closed pull request is not allowed') h.flash(msg, category='warning') return redirect( h.url('changeset_home', repo_name=repo_name, revision=revision)) action_logger(self.authuser, 'user_commented_revision:%s' % revision, c.db_repo, self.ip_addr, self.sa) Session().commit() if not request.environ.get('HTTP_X_PARTIAL_XHR'): return redirect( h.url('changeset_home', repo_name=repo_name, revision=revision)) #only ajax below data = { 'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))), } if comm: data.update(comm.get_dict()) data.update({ 'rendered_text': render('changeset/changeset_comment_block.html') }) return data
def log_push_action(ui, repo, **kwargs): """ Maps user last push action to new changeset id, from mercurial :param ui: :param repo: repo object containing the `ui` object """ ex = _extract_extras() action_tmpl = ex.action + ':%s' revs = [] if ex.scm == 'hg': node = kwargs['node'] def get_revs(repo, rev_opt): if rev_opt: revs = revrange(repo, rev_opt) if len(revs) == 0: return (nullrev, nullrev) return max(revs), min(revs) else: return len(repo) - 1, 0 stop, start = get_revs(repo, [node + ':']) _h = binascii.hexlify revs = [_h(repo[r].node()) for r in xrange(start, stop + 1)] elif ex.scm == 'git': revs = kwargs.get('_git_revs', []) if '_git_revs' in kwargs: kwargs.pop('_git_revs') action = action_tmpl % ','.join(revs) action_logger(ex.username, action, ex.repository, ex.ip, commit=True) # extension hook call from kallithea import EXTENSIONS callback = getattr(EXTENSIONS, 'PUSH_HOOK', None) if callable(callback): kw = {'pushed_revs': revs} kw.update(ex) callback(**kw) if ex.make_lock is not None and not ex.make_lock: Repository.unlock(Repository.get_by_repo_name(ex.repository)) msg = 'Released lock on repo `%s`\n' % ex.repository sys.stdout.write(msg) if ex.locked_by[0]: locked_by = User.get(ex.locked_by[0]).username _http_ret = HTTPLockedRC(ex.repository, locked_by) if str(_http_ret.code).startswith('2'): #2xx Codes don't raise exceptions sys.stdout.write(_http_ret.title) return 0
def log_push_action(ui, repo, **kwargs): """ Maps user last push action to new changeset id, from mercurial :param ui: :param repo: repo object containing the `ui` object """ ex = _extract_extras() action_tmpl = ex.action + ':%s' revs = [] if ex.scm == 'hg': node = kwargs['node'] def get_revs(repo, rev_opt): if rev_opt: revs = revrange(repo, rev_opt) if len(revs) == 0: return (nullrev, nullrev) return max(revs), min(revs) else: return len(repo) - 1, 0 stop, start = get_revs(repo, [node + ':']) _h = binascii.hexlify revs = [_h(repo[r].node()) for r in xrange(start, stop + 1)] elif ex.scm == 'git': revs = kwargs.get('_git_revs', []) if '_git_revs' in kwargs: kwargs.pop('_git_revs') action = action_tmpl % ','.join(revs) action_logger(ex.username, action, ex.repository, ex.ip, commit=True) # extension hook call from kallithea import EXTENSIONS callback = getattr(EXTENSIONS, 'PUSH_HOOK', None) if callable(callback): kw = {'pushed_revs': revs} kw.update(ex) callback(**kw) if ex.make_lock is not None and not ex.make_lock: Repository.unlock(Repository.get_by_repo_name(ex.repository)) msg = 'Released lock on repo `%s`\n' % ex.repository sys.stdout.write(msg) if ex.locked_by[0]: locked_by = User.get(ex.locked_by[0]).username _http_ret = HTTPLockedRC(ex.repository, locked_by) if str(_http_ret.code).startswith('2'): #2xx Codes don't raise exceptions sys.stdout.write(_http_ret.title) return 0
def comment(self, repo_name, revision): status = request.POST.get('changeset_status') text = request.POST.get('text', '').strip() or _('No comments.') c.co = comm = ChangesetCommentsModel().create( text=text, repo=c.db_repo.repo_id, user=c.authuser.user_id, revision=revision, f_path=request.POST.get('f_path'), line_no=request.POST.get('line'), status_change=(ChangesetStatus.get_status_lbl(status) if status else None) ) # get status if set ! if status: # if latest status was from pull request and it's closed # disallow changing status ! # dont_allow_on_closed_pull_request = True ! try: ChangesetStatusModel().set_status( c.db_repo.repo_id, status, c.authuser.user_id, comm, revision=revision, dont_allow_on_closed_pull_request=True ) except StatusChangeOnClosedPullRequestError: log.error(traceback.format_exc()) msg = _('Changing status on a changeset associated with ' 'a closed pull request is not allowed') h.flash(msg, category='warning') return redirect(h.url('changeset_home', repo_name=repo_name, revision=revision)) action_logger(self.authuser, 'user_commented_revision:%s' % revision, c.db_repo, self.ip_addr, self.sa) Session().commit() if not request.environ.get('HTTP_X_PARTIAL_XHR'): return redirect(h.url('changeset_home', repo_name=repo_name, revision=revision)) #only ajax below data = { 'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))), } if comm: data.update(comm.get_dict()) data.update({'rendered_text': render('changeset/changeset_comment_block.html')}) return data
def update(self, repo_name): """ PUT /repos/repo_name: Update an existing item""" # Forms posted to this method should contain a hidden field: # <input type="hidden" name="_method" value="PUT" /> # Or using helpers: # h.form(url('put_repo', repo_name=ID), # method='put') # url('put_repo', repo_name=ID) c.repo_info = self._load_repo(repo_name) self.__load_defaults(c.repo_info) c.active = 'settings' c.repo_fields = RepositoryField.query() \ .filter(RepositoryField.repository == c.repo_info).all() repo_model = RepoModel() changed_name = repo_name repo = Repository.get_by_repo_name(repo_name) old_data = { 'repo_name': repo_name, 'repo_group': repo.group.get_dict() if repo.group else {}, 'repo_type': repo.repo_type, } _form = RepoForm(edit=True, old_data=old_data, repo_groups=c.repo_groups, landing_revs=c.landing_revs_choices)() try: form_result = _form.to_python(dict(request.POST)) repo = repo_model.update(repo_name, **form_result) ScmModel().mark_for_invalidation(repo_name) h.flash(_('Repository %s updated successfully') % repo_name, category='success') changed_name = repo.repo_name action_logger(self.authuser, 'admin_updated_repo', changed_name, self.ip_addr, self.sa) Session().commit() except formencode.Invalid as errors: log.info(errors) defaults = self.__load_data(repo_name) defaults.update(errors.value) c.users_array = repo_model.get_users_js() return htmlfill.render( render('admin/repos/repo_edit.html'), defaults=defaults, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8", force_defaults=False) except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred during update of repository %s') \ % repo_name, category='error') raise HTTPFound(location=url('edit_repo', repo_name=changed_name))
def log_push_action(ui, repo, **kwargs): """ Register that changes have been pushed. Mercurial invokes this directly as a hook, git uses handle_git_receive. """ ex = _extract_extras() action_tmpl = ex.action + ':%s' revs = [] if ex.scm == 'hg': node = kwargs['node'] def get_revs(repo, rev_opt): if rev_opt: revs = revrange(repo, rev_opt) if len(revs) == 0: return (nullrev, nullrev) return max(revs), min(revs) else: return len(repo) - 1, 0 stop, start = get_revs(repo, [node + ':']) _h = binascii.hexlify revs = [_h(repo[r].node()) for r in xrange(start, stop + 1)] elif ex.scm == 'git': revs = kwargs.get('_git_revs', []) if '_git_revs' in kwargs: kwargs.pop('_git_revs') action = action_tmpl % ','.join(revs) action_logger(ex.username, action, ex.repository, ex.ip, commit=True) # extension hook call from kallithea import EXTENSIONS callback = getattr(EXTENSIONS, 'PUSH_HOOK', None) if callable(callback): kw = {'pushed_revs': revs} kw.update(ex) callback(**kw) if ex.make_lock is not None and not ex.make_lock: Repository.unlock(Repository.get_by_repo_name(ex.repository)) ui.status(safe_str('Released lock on repo `%s`\n' % ex.repository)) if ex.locked_by[0]: locked_by = User.get(ex.locked_by[0]).username _http_ret = HTTPLockedRC(ex.repository, locked_by) if str(_http_ret.code).startswith('2'): #2xx Codes don't raise exceptions ui.status(safe_str(_http_ret.title)) return 0
def log_push_action(ui, repo, **kwargs): """ Register that changes have been pushed. Mercurial invokes this directly as a hook, git uses handle_git_receive. """ ex = _extract_extras() action_tmpl = ex.action + ':%s' revs = [] if ex.scm == 'hg': node = kwargs['node'] def get_revs(repo, rev_opt): if rev_opt: revs = revrange(repo, rev_opt) if len(revs) == 0: return (nullrev, nullrev) return max(revs), min(revs) else: return len(repo) - 1, 0 stop, start = get_revs(repo, [node + ':']) _h = binascii.hexlify revs = [_h(repo[r].node()) for r in xrange(start, stop + 1)] elif ex.scm == 'git': revs = kwargs.get('_git_revs', []) if '_git_revs' in kwargs: kwargs.pop('_git_revs') action = action_tmpl % ','.join(revs) action_logger(ex.username, action, ex.repository, ex.ip, commit=True) # extension hook call from kallithea import EXTENSIONS callback = getattr(EXTENSIONS, 'PUSH_HOOK', None) if callable(callback): kw = {'pushed_revs': revs} kw.update(ex) callback(**kw) if ex.make_lock is not None and not ex.make_lock: Repository.unlock(Repository.get_by_repo_name(ex.repository)) ui.status(safe_str('Released lock on repo `%s`\n' % ex.repository)) if ex.locked_by[0]: locked_by = User.get(ex.locked_by[0]).username _http_ret = HTTPLockedRC(ex.repository, locked_by) if str(_http_ret.code).startswith('2'): #2xx Codes don't raise exceptions ui.status(safe_str(_http_ret.title)) return 0
def update(self, id): """PUT /users/id: Update an existing item""" # Forms posted to this method should contain a hidden field: # <input type="hidden" name="_method" value="PUT" /> # Or using helpers: # h.form(url('update_user', id=ID), # method='put') # url('user', id=ID) c.active = 'profile' user_model = UserModel() c.user = user_model.get(id) c.extern_type = c.user.extern_type c.extern_name = c.user.extern_name c.perm_user = AuthUser(user_id=id, ip_addr=self.ip_addr) _form = UserForm(edit=True, old_data={ 'user_id': id, 'email': c.user.email })() form_result = {} try: form_result = _form.to_python(dict(request.POST)) skip_attrs = ['extern_type', 'extern_name'] #TODO: plugin should define if username can be updated if c.extern_type != kallithea.EXTERN_TYPE_INTERNAL: # forbid updating username for external accounts skip_attrs.append('username') user_model.update(id, form_result, skip_attrs=skip_attrs) usr = form_result['username'] action_logger(self.authuser, 'admin_updated_user:%s' % usr, None, self.ip_addr, self.sa) h.flash(_('User updated successfully'), category='success') Session().commit() except formencode.Invalid, errors: defaults = errors.value e = errors.error_dict or {} defaults.update({ 'create_repo_perm': user_model.has_perm(id, 'hg.create.repository'), 'fork_repo_perm': user_model.has_perm(id, 'hg.fork.repository'), '_method': 'put' }) return htmlfill.render(render('admin/users/user_edit.html'), defaults=defaults, errors=e, prefix_error=False, encoding="UTF-8", force_defaults=False)
def update(self, repo_name): """ PUT /repos/repo_name: Update an existing item""" # Forms posted to this method should contain a hidden field: # <input type="hidden" name="_method" value="PUT" /> # Or using helpers: # h.form(url('repo', repo_name=ID), # method='put') # url('repo', repo_name=ID) c.repo_info = self._load_repo(repo_name) c.active = 'settings' c.repo_fields = RepositoryField.query()\ .filter(RepositoryField.repository == c.repo_info).all() self.__load_defaults(c.repo_info) repo_model = RepoModel() changed_name = repo_name #override the choices with extracted revisions ! choices, c.landing_revs = ScmModel().get_repo_landing_revs(repo_name) c.landing_revs_choices = choices repo = Repository.get_by_repo_name(repo_name) old_data = { 'repo_name': repo_name, 'repo_group': repo.group.get_dict() if repo.group else {}, 'repo_type': repo.repo_type, } _form = RepoForm(edit=True, old_data=old_data, repo_groups=c.repo_groups_choices, landing_revs=c.landing_revs_choices)() try: form_result = _form.to_python(dict(request.POST)) repo = repo_model.update(repo_name, **form_result) ScmModel().mark_for_invalidation(repo_name) h.flash(_('Repository %s updated successfully') % repo_name, category='success') changed_name = repo.repo_name action_logger(self.authuser, 'admin_updated_repo', changed_name, self.ip_addr, self.sa) Session().commit() except formencode.Invalid, errors: defaults = self.__load_data(repo_name) defaults.update(errors.value) return htmlfill.render(render('admin/repos/repo_edit.html'), defaults=defaults, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8", force_defaults=False)
def update(self, id): """PUT /user_groups/id: Update an existing item""" # Forms posted to this method should contain a hidden field: # <input type="hidden" name="_method" value="PUT" /> # Or using helpers: # h.form(url('users_group', id=ID), # method='put') # url('users_group', id=ID) c.user_group = UserGroup.get_or_404(id) c.active = 'settings' self.__load_data(id) available_members = [safe_unicode(x[0]) for x in c.available_members] users_group_form = UserGroupForm(edit=True, old_data=c.user_group.get_dict(), available_members=available_members)() try: form_result = users_group_form.to_python(request.POST) UserGroupModel().update(c.user_group, form_result) gr = form_result['users_group_name'] action_logger(self.authuser, 'admin_updated_users_group:%s' % gr, None, self.ip_addr, self.sa) h.flash(_('Updated user group %s') % gr, category='success') Session().commit() except formencode.Invalid, errors: ug_model = UserGroupModel() defaults = errors.value e = errors.error_dict or {} defaults.update({ 'create_repo_perm': ug_model.has_perm(id, 'hg.create.repository'), 'fork_repo_perm': ug_model.has_perm(id, 'hg.fork.repository'), '_method': 'put' }) return htmlfill.render( render('admin/user_groups/user_group_edit.html'), defaults=defaults, errors=e, prefix_error=False, encoding="UTF-8", force_defaults=False)
def update(self, id): """PUT /users/id: Update an existing item""" # Forms posted to this method should contain a hidden field: # <input type="hidden" name="_method" value="PUT" /> # Or using helpers: # h.form(url('update_user', id=ID), # method='put') # url('user', id=ID) c.active = 'profile' user_model = UserModel() c.user = user_model.get(id) c.extern_type = c.user.extern_type c.extern_name = c.user.extern_name c.perm_user = AuthUser(user_id=id, ip_addr=self.ip_addr) _form = UserForm(edit=True, old_data={'user_id': id, 'email': c.user.email})() form_result = {} try: form_result = _form.to_python(dict(request.POST)) skip_attrs = ['extern_type', 'extern_name'] #TODO: plugin should define if username can be updated if c.extern_type != kallithea.EXTERN_TYPE_INTERNAL: # forbid updating username for external accounts skip_attrs.append('username') user_model.update(id, form_result, skip_attrs=skip_attrs) usr = form_result['username'] action_logger(self.authuser, 'admin_updated_user:%s' % usr, None, self.ip_addr, self.sa) h.flash(_('User updated successfully'), category='success') Session().commit() except formencode.Invalid, errors: defaults = errors.value e = errors.error_dict or {} defaults.update({ 'create_repo_perm': user_model.has_perm(id, 'hg.create.repository'), 'fork_repo_perm': user_model.has_perm(id, 'hg.fork.repository'), '_method': 'put' }) return htmlfill.render( render('admin/users/user_edit.html'), defaults=defaults, errors=e, prefix_error=False, encoding="UTF-8", force_defaults=False)
def delete(self, repo_name): """ DELETE /repos/repo_name: Delete an existing item""" # Forms posted to this method should contain a hidden field: # <input type="hidden" name="_method" value="DELETE" /> # Or using helpers: # h.form(url('repo', repo_name=ID), # method='delete') # url('repo', repo_name=ID) repo_model = RepoModel() repo = repo_model.get_by_repo_name(repo_name) if not repo: h.not_mapped_error(repo_name) return redirect(url('repos')) try: _forks = repo.forks.count() handle_forks = None if _forks and request.POST.get('forks'): do = request.POST['forks'] if do == 'detach_forks': handle_forks = 'detach' h.flash(_('Detached %s forks') % _forks, category='success') elif do == 'delete_forks': handle_forks = 'delete' h.flash(_('Deleted %s forks') % _forks, category='success') repo_model.delete(repo, forks=handle_forks) action_logger(self.authuser, 'admin_deleted_repo', repo_name, self.ip_addr, self.sa) ScmModel().mark_for_invalidation(repo_name) h.flash(_('Deleted repository %s') % repo_name, category='success') Session().commit() except AttachedForksError: h.flash(_('Cannot delete %s it still contains attached forks') % repo_name, category='warning') except Exception: log.error(traceback.format_exc()) h.flash(_('An error occurred during deletion of %s') % repo_name, category='error') if repo.group: return redirect( url('repos_group_home', group_name=repo.group.group_name)) return redirect(url('repos'))
def update(self, id): """PUT /user_groups/id: Update an existing item""" # Forms posted to this method should contain a hidden field: # <input type="hidden" name="_method" value="PUT" /> # Or using helpers: # h.form(url('users_group', id=ID), # method='put') # url('users_group', id=ID) c.user_group = UserGroup.get_or_404(id) c.active = 'settings' self.__load_data(id) available_members = [safe_unicode(x[0]) for x in c.available_members] users_group_form = UserGroupForm(edit=True, old_data=c.user_group.get_dict(), available_members=available_members)() try: form_result = users_group_form.to_python(request.POST) UserGroupModel().update(c.user_group, form_result) gr = form_result['users_group_name'] action_logger(self.authuser, 'admin_updated_users_group:%s' % gr, None, self.ip_addr, self.sa) h.flash(_('Updated user group %s') % gr, category='success') Session().commit() except formencode.Invalid, errors: ug_model = UserGroupModel() defaults = errors.value e = errors.error_dict or {} defaults.update({ 'create_repo_perm': ug_model.has_perm(id, 'hg.create.repository'), 'fork_repo_perm': ug_model.has_perm(id, 'hg.fork.repository'), '_method': 'put' }) return htmlfill.render( render('admin/user_groups/user_group_edit.html'), defaults=defaults, errors=e, prefix_error=False, encoding="UTF-8", force_defaults=False)
def update(self, repo_name): c.repo_info = self._load_repo() self.__load_defaults(c.repo_info) c.active = 'settings' c.repo_fields = RepositoryField.query() \ .filter(RepositoryField.repository == c.repo_info).all() repo_model = RepoModel() changed_name = repo_name repo = Repository.get_by_repo_name(repo_name) old_data = { 'repo_name': repo_name, 'repo_group': repo.group.get_dict() if repo.group else {}, 'repo_type': repo.repo_type, } _form = RepoForm(edit=True, old_data=old_data, repo_groups=c.repo_groups, landing_revs=c.landing_revs_choices)() try: form_result = _form.to_python(dict(request.POST)) repo = repo_model.update(repo_name, **form_result) ScmModel().mark_for_invalidation(repo_name) h.flash(_('Repository %s updated successfully') % repo_name, category='success') changed_name = repo.repo_name action_logger(request.authuser, 'admin_updated_repo', changed_name, request.ip_addr) Session().commit() except formencode.Invalid as errors: log.info(errors) defaults = self.__load_data() defaults.update(errors.value) return htmlfill.render(render('admin/repos/repo_edit.html'), defaults=defaults, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8", force_defaults=False) except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred during update of repository %s') % repo_name, category='error') raise HTTPFound(location=url('edit_repo', repo_name=changed_name))
def comment(self, repo_name, revision): assert request.environ.get('HTTP_X_PARTIAL_XHR') status = request.POST.get('changeset_status') text = request.POST.get('text', '').strip() c.comment = create_comment( text, status, revision=revision, f_path=request.POST.get('f_path'), line_no=request.POST.get('line'), ) # get status if set ! if status: # if latest status was from pull request and it's closed # disallow changing status ! RLY? try: ChangesetStatusModel().set_status( c.db_repo.repo_id, status, request.authuser.user_id, c.comment, revision=revision, dont_allow_on_closed_pull_request=True, ) except StatusChangeOnClosedPullRequestError: log.debug('cannot change status on %s with closed pull request', revision) raise HTTPBadRequest() action_logger(request.authuser, 'user_commented_revision:%s' % revision, c.db_repo, request.ip_addr) Session().commit() data = { 'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))), } if c.comment is not None: data.update(c.comment.get_dict()) data.update({'rendered_text': render('changeset/changeset_comment_block.html')}) return data
def update(self, id): """PUT /users/id: Update an existing item""" # Forms posted to this method should contain a hidden field: # <input type="hidden" name="_method" value="PUT" /> # Or using helpers: # h.form(url('update_user', id=ID), # method='put') # url('user', id=ID) user_model = UserModel() user = user_model.get(id) _form = UserForm(edit=True, old_data={'user_id': id, 'email': user.email})() form_result = {} try: form_result = _form.to_python(dict(request.POST)) skip_attrs = ['extern_type', 'extern_name', ] + auth_modules.get_managed_fields(user) user_model.update(id, form_result, skip_attrs=skip_attrs) usr = form_result['username'] action_logger(self.authuser, 'admin_updated_user:%s' % usr, None, self.ip_addr, self.sa) h.flash(_('User updated successfully'), category='success') Session().commit() except formencode.Invalid as errors: defaults = errors.value e = errors.error_dict or {} defaults.update({ 'create_repo_perm': user_model.has_perm(id, 'hg.create.repository'), 'fork_repo_perm': user_model.has_perm(id, 'hg.fork.repository'), '_method': 'put' }) return htmlfill.render( self._render_edit_profile(user), defaults=defaults, errors=e, prefix_error=False, encoding="UTF-8", force_defaults=False) except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred during update of user %s') \ % form_result.get('username'), category='error') raise HTTPFound(location=url('edit_user', id=id))
def update(self, id): c.user_group = UserGroup.get_or_404(id) c.active = 'settings' self.__load_data(id) available_members = [safe_str(x[0]) for x in c.available_members] users_group_form = UserGroupForm(edit=True, old_data=c.user_group.get_dict(), available_members=available_members)() try: form_result = users_group_form.to_python(request.POST) UserGroupModel().update(c.user_group, form_result) gr = form_result['users_group_name'] action_logger(request.authuser, 'admin_updated_users_group:%s' % gr, None, request.ip_addr) h.flash(_('Updated user group %s') % gr, category='success') Session().commit() except formencode.Invalid as errors: ug_model = UserGroupModel() defaults = errors.value e = errors.error_dict or {} defaults.update({ 'create_repo_perm': ug_model.has_perm(id, 'hg.create.repository'), 'fork_repo_perm': ug_model.has_perm(id, 'hg.fork.repository'), }) return htmlfill.render( render('admin/user_groups/user_group_edit.html'), defaults=defaults, errors=e, prefix_error=False, encoding="UTF-8", force_defaults=False) except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred during update of user group %s') % request.POST.get('users_group_name'), category='error') raise HTTPFound(location=url('edit_users_group', id=id))
def update(self, id): c.user_group = UserGroup.get_or_404(id) c.active = 'settings' self.__load_data(id) available_members = [safe_unicode(x[0]) for x in c.available_members] users_group_form = UserGroupForm(edit=True, old_data=c.user_group.get_dict(), available_members=available_members)() try: form_result = users_group_form.to_python(request.POST) UserGroupModel().update(c.user_group, form_result) gr = form_result['users_group_name'] action_logger(request.authuser, 'admin_updated_users_group:%s' % gr, None, request.ip_addr) h.flash(_('Updated user group %s') % gr, category='success') Session().commit() except formencode.Invalid as errors: ug_model = UserGroupModel() defaults = errors.value e = errors.error_dict or {} defaults.update({ 'create_repo_perm': ug_model.has_perm(id, 'hg.create.repository'), 'fork_repo_perm': ug_model.has_perm(id, 'hg.fork.repository'), }) return htmlfill.render( render('admin/user_groups/user_group_edit.html'), defaults=defaults, errors=e, prefix_error=False, encoding="UTF-8", force_defaults=False) except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred during update of user group %s') \ % request.POST.get('users_group_name'), category='error') raise HTTPFound(location=url('edit_users_group', id=id))
def delete(self, repo_name): """ DELETE /repos/repo_name: Delete an existing item""" # Forms posted to this method should contain a hidden field: # <input type="hidden" name="_method" value="DELETE" /> # Or using helpers: # h.form(url('repo', repo_name=ID), # method='delete') # url('repo', repo_name=ID) repo_model = RepoModel() repo = repo_model.get_by_repo_name(repo_name) if not repo: h.not_mapped_error(repo_name) return redirect(url('repos')) try: _forks = repo.forks.count() handle_forks = None if _forks and request.POST.get('forks'): do = request.POST['forks'] if do == 'detach_forks': handle_forks = 'detach' h.flash(_('Detached %s forks') % _forks, category='success') elif do == 'delete_forks': handle_forks = 'delete' h.flash(_('Deleted %s forks') % _forks, category='success') repo_model.delete(repo, forks=handle_forks) action_logger(self.authuser, 'admin_deleted_repo', repo_name, self.ip_addr, self.sa) ScmModel().mark_for_invalidation(repo_name) h.flash(_('Deleted repository %s') % repo_name, category='success') Session().commit() except AttachedForksError: h.flash(_('Cannot delete %s it still contains attached forks') % repo_name, category='warning') except Exception: log.error(traceback.format_exc()) h.flash(_('An error occurred during deletion of %s') % repo_name, category='error') if repo.group: return redirect(url('repos_group_home', group_name=repo.group.group_name)) return redirect(url('repos'))
def log_pull_action(ui, repo, **kwargs): """Logs user last pull action Called as Mercurial hook outgoing.pull_logger or from Kallithea before invoking Git. Does *not* use the action from the hook environment but is always 'pull'. """ ex = get_hook_environment() user = User.get_by_username(ex.username) action = 'pull' action_logger(user, action, ex.repository, ex.ip, commit=True) # extension hook call from kallithea import EXTENSIONS callback = getattr(EXTENSIONS, 'PULL_HOOK', None) if callable(callback): kw = {} kw.update(ex) callback(**kw) return 0
def delete(self, repo_name): repo_model = RepoModel() repo = repo_model.get_by_repo_name(repo_name) if not repo: h.not_mapped_error(repo_name) raise HTTPFound(location=url('repos')) try: _forks = repo.forks.count() handle_forks = None if _forks and request.POST.get('forks'): do = request.POST['forks'] if do == 'detach_forks': handle_forks = 'detach' h.flash(_('Detached %s forks') % _forks, category='success') elif do == 'delete_forks': handle_forks = 'delete' h.flash(_('Deleted %s forks') % _forks, category='success') repo_model.delete(repo, forks=handle_forks) action_logger(request.authuser, 'admin_deleted_repo', repo_name, request.ip_addr) ScmModel().mark_for_invalidation(repo_name) h.flash(_('Deleted repository %s') % repo_name, category='success') Session().commit() except AttachedForksError: h.flash(_('Cannot delete repository %s which still has forks') % repo_name, category='warning') except Exception: log.error(traceback.format_exc()) h.flash(_('An error occurred during deletion of %s') % repo_name, category='error') if repo.group: raise HTTPFound(location=url('repos_group_home', group_name=repo.group.group_name)) raise HTTPFound(location=url('repos'))
def create(self): """POST /users: Create a new item""" # url('users') c.default_extern_type = auth_modules.auth_internal.KallitheaAuthPlugin.name user_model = UserModel() user_form = UserForm()() try: form_result = user_form.to_python(dict(request.POST)) user = user_model.create(form_result) usr = form_result['username'] action_logger(self.authuser, 'admin_created_user:%s' % usr, None, self.ip_addr, self.sa) h.flash(h.literal(_('Created user %s') % h.link_to(h.escape(usr), url('edit_user', id=user.user_id))), category='success') Session().commit() except formencode.Invalid, errors: return htmlfill.render( render('admin/users/user_add.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8", force_defaults=False)
def process_pushed_raw_ids(revs): """ Register that changes have been added to the repo - log the action *and* invalidate caches. Called from Mercurial changegroup.kallithea_log_push_action calling hook log_push_action, or from the Git post-receive hook calling handle_git_post_receive ... or from scm _handle_push. """ ex = get_hook_environment() action = '%s:%s' % (ex.action, ','.join(revs)) action_logger(ex.username, action, ex.repository, ex.ip, commit=True) from kallithea.model.scm import ScmModel ScmModel().mark_for_invalidation(ex.repository) # extension hook call from kallithea import EXTENSIONS callback = getattr(EXTENSIONS, 'PUSH_HOOK', None) if callable(callback): kw = {'pushed_revs': revs} kw.update(ex) callback(**kw)
def update(self, id): user_model = UserModel() user = user_model.get(id) _form = UserForm(edit=True, old_data={'user_id': id, 'email': user.email})() form_result = {} try: form_result = _form.to_python(dict(request.POST)) skip_attrs = ['extern_type', 'extern_name', ] + auth_modules.get_managed_fields(user) user_model.update(id, form_result, skip_attrs=skip_attrs) usr = form_result['username'] action_logger(request.authuser, 'admin_updated_user:%s' % usr, None, request.ip_addr) h.flash(_('User updated successfully'), category='success') Session().commit() except formencode.Invalid as errors: defaults = errors.value e = errors.error_dict or {} defaults.update({ 'create_repo_perm': user_model.has_perm(id, 'hg.create.repository'), 'fork_repo_perm': user_model.has_perm(id, 'hg.fork.repository'), }) return htmlfill.render( self._render_edit_profile(user), defaults=defaults, errors=e, prefix_error=False, encoding="UTF-8", force_defaults=False) except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred during update of user %s') \ % form_result.get('username'), category='error') raise HTTPFound(location=url('edit_user', id=id))
def create(self): """POST /users: Create a new item""" # url('users') c.default_extern_type = auth_modules.auth_internal.KallitheaAuthPlugin.name user_model = UserModel() user_form = UserForm()() try: form_result = user_form.to_python(dict(request.POST)) user = user_model.create(form_result) usr = form_result['username'] action_logger(self.authuser, 'admin_created_user:%s' % usr, None, self.ip_addr, self.sa) h.flash(h.literal( _('Created user %s') % h.link_to(h.escape(usr), url('edit_user', id=user.user_id))), category='success') Session().commit() except formencode.Invalid, errors: return htmlfill.render(render('admin/users/user_add.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8", force_defaults=False)
def comment(self, repo_name, pull_request_id): pull_request = PullRequest.get_or_404(pull_request_id) status = 0 close_pr = False allowed_to_change_status = self._get_is_allowed_change_status(pull_request) if allowed_to_change_status: status = request.POST.get('changeset_status') close_pr = request.POST.get('save_close') text = request.POST.get('text', '').strip() or _('No comments.') if close_pr: text = _('Closing.') + '\n' + text comm = ChangesetCommentsModel().create( text=text, repo=c.db_repo.repo_id, user=c.authuser.user_id, pull_request=pull_request_id, f_path=request.POST.get('f_path'), line_no=request.POST.get('line'), status_change=(ChangesetStatus.get_status_lbl(status) if status and allowed_to_change_status else None), closing_pr=close_pr ) action_logger(self.authuser, 'user_commented_pull_request:%s' % pull_request_id, c.db_repo, self.ip_addr, self.sa) if allowed_to_change_status: # get status if set ! if status: ChangesetStatusModel().set_status( c.db_repo.repo_id, status, c.authuser.user_id, comm, pull_request=pull_request_id ) if close_pr: PullRequestModel().close_pull_request(pull_request_id) action_logger(self.authuser, 'user_closed_pull_request:%s' % pull_request_id, c.db_repo, self.ip_addr, self.sa) Session().commit() if not request.environ.get('HTTP_X_PARTIAL_XHR'): return redirect(pull_request.url()) data = { 'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))), } if comm: c.co = comm data.update(comm.get_dict()) data.update({'rendered_text': render('changeset/changeset_comment_block.html')}) return data
def create_repo_fork(form_data, cur_user): """ Creates a fork of repository using interval VCS methods :param form_data: :param cur_user: """ from kallithea.model.repo import RepoModel from kallithea.model.user import UserModel log = get_logger(create_repo_fork) DBS = get_session() base_path = Repository.base_path() cur_user = UserModel(DBS)._get_user(cur_user) repo_name = form_data['repo_name'] # fork in this case repo_name_full = form_data['repo_name_full'] repo_type = form_data['repo_type'] owner = cur_user private = form_data['private'] clone_uri = form_data.get('clone_uri') repo_group = form_data['repo_group'] landing_rev = form_data['landing_rev'] copy_fork_permissions = form_data.get('copy_permissions') try: fork_of = RepoModel(DBS)._get_repo(form_data.get('fork_parent_id')) RepoModel(DBS)._create_repo( repo_name=repo_name_full, repo_type=repo_type, description=form_data['description'], owner=owner, private=private, clone_uri=clone_uri, repo_group=repo_group, landing_rev=landing_rev, fork_of=fork_of, copy_fork_permissions=copy_fork_permissions ) action_logger(cur_user, 'user_forked_repo:%s' % repo_name_full, fork_of.repo_name, '', DBS) DBS.commit() update_after_clone = form_data['update_after_clone'] # FIXME - unused! source_repo_path = os.path.join(base_path, fork_of.repo_name) # now create this repo on Filesystem RepoModel(DBS)._create_filesystem_repo( repo_name=repo_name, repo_type=repo_type, repo_group=RepoModel(DBS)._get_repo_group(repo_group), clone_uri=source_repo_path, ) repo = Repository.get_by_repo_name(repo_name_full) log_create_repository(repo.get_dict(), created_by=owner.username) # update repo changeset caches initially repo.update_changeset_cache() # set new created state repo.set_state(Repository.STATE_CREATED) DBS.commit() except Exception as e: log.warning('Exception %s occurred when forking repository, ' 'doing cleanup...' % e) #rollback things manually ! repo = Repository.get_by_repo_name(repo_name_full) if repo: Repository.delete(repo.repo_id) DBS.commit() RepoModel(DBS)._delete_filesystem_repo(repo) raise # it's an odd fix to make celery fail task when exception occurs def on_failure(self, *args, **kwargs): pass return True
def archivefile(self, repo_name, fname): fileformat = None revision = None ext = None subrepos = request.GET.get('subrepos') == 'true' for a_type, ext_data in settings.ARCHIVE_SPECS.items(): archive_spec = fname.split(ext_data[1]) if len(archive_spec) == 2 and archive_spec[1] == '': fileformat = a_type or ext_data[1] revision = archive_spec[0] ext = ext_data[1] try: dbrepo = RepoModel().get_by_repo_name(repo_name) if not dbrepo.enable_downloads: return _('Downloads disabled') # TODO: do something else? if c.db_repo_scm_instance.alias == 'hg': # patch and reset hooks section of UI config to not run any # hooks on fetching archives with subrepos for k, v in c.db_repo_scm_instance._repo.ui.configitems('hooks'): c.db_repo_scm_instance._repo.ui.setconfig('hooks', k, None) cs = c.db_repo_scm_instance.get_changeset(revision) content_type = settings.ARCHIVE_SPECS[fileformat][0] except ChangesetDoesNotExistError: return _('Unknown revision %s') % revision except EmptyRepositoryError: return _('Empty repository') except (ImproperArchiveTypeError, KeyError): return _('Unknown archive type') from kallithea import CONFIG rev_name = cs.raw_id[:12] archive_name = '%s-%s%s' % (safe_str(repo_name.replace('/', '_')), safe_str(rev_name), ext) archive_path = None cached_archive_path = None archive_cache_dir = CONFIG.get('archive_cache_dir') if archive_cache_dir and not subrepos: # TOOD: subrepo caching? if not os.path.isdir(archive_cache_dir): os.makedirs(archive_cache_dir) cached_archive_path = os.path.join(archive_cache_dir, archive_name) if os.path.isfile(cached_archive_path): log.debug('Found cached archive in %s', cached_archive_path) archive_path = cached_archive_path else: log.debug('Archive %s is not yet cached', archive_name) if archive_path is None: # generate new archive fd, archive_path = tempfile.mkstemp() log.debug('Creating new temp archive in %s', archive_path) with os.fdopen(fd, 'wb') as stream: cs.fill_archive(stream=stream, kind=fileformat, subrepos=subrepos) # stream (and thus fd) has been closed by cs.fill_archive if cached_archive_path is not None: # we generated the archive - move it to cache log.debug('Storing new archive in %s', cached_archive_path) shutil.move(archive_path, cached_archive_path) archive_path = cached_archive_path def get_chunked_archive(archive_path): stream = open(archive_path, 'rb') while True: data = stream.read(16 * 1024) if not data: break yield data stream.close() if archive_path != cached_archive_path: log.debug('Destroying temp archive %s', archive_path) os.remove(archive_path) action_logger(user=c.authuser, action='user_downloaded_archive:%s' % (archive_name), repo=repo_name, ipaddr=self.ip_addr, commit=True) response.content_disposition = str('attachment; filename=%s' % (archive_name)) response.content_type = str(content_type) return get_chunked_archive(archive_path)
def create_repo_fork(form_data, cur_user): """ Creates a fork of repository using interval VCS methods :param form_data: :param cur_user: """ from kallithea.model.repo import RepoModel from kallithea.model.user import UserModel log = get_logger(create_repo_fork) DBS = get_session() base_path = Repository.base_path() cur_user = UserModel(DBS)._get_user(cur_user) repo_name = form_data['repo_name'] # fork in this case repo_name_full = form_data['repo_name_full'] repo_type = form_data['repo_type'] owner = cur_user private = form_data['private'] clone_uri = form_data.get('clone_uri') repo_group = form_data['repo_group'] landing_rev = form_data['landing_rev'] copy_fork_permissions = form_data.get('copy_permissions') try: fork_of = RepoModel(DBS)._get_repo(form_data.get('fork_parent_id')) RepoModel(DBS)._create_repo( repo_name=repo_name_full, repo_type=repo_type, description=form_data['description'], owner=owner, private=private, clone_uri=clone_uri, repo_group=repo_group, landing_rev=landing_rev, fork_of=fork_of, copy_fork_permissions=copy_fork_permissions) action_logger(cur_user, 'user_forked_repo:%s' % repo_name_full, fork_of.repo_name, '', DBS) DBS.commit() update_after_clone = form_data['update_after_clone'] # FIXME - unused! source_repo_path = os.path.join(base_path, fork_of.repo_name) # now create this repo on Filesystem RepoModel(DBS)._create_filesystem_repo( repo_name=repo_name, repo_type=repo_type, repo_group=RepoModel(DBS)._get_repo_group(repo_group), clone_uri=source_repo_path, ) repo = Repository.get_by_repo_name(repo_name_full) log_create_repository(repo.get_dict(), created_by=owner.username) # update repo changeset caches initially repo.update_changeset_cache() # set new created state repo.set_state(Repository.STATE_CREATED) DBS.commit() except Exception, e: log.warning('Exception %s occurred when forking repository, ' 'doing cleanup...' % e) #rollback things manually ! repo = Repository.get_by_repo_name(repo_name_full) if repo: Repository.delete(repo.repo_id) DBS.commit() RepoModel(DBS)._delete_filesystem_repo(repo) raise
def create_repo(form_data, cur_user): from kallithea.model.repo import RepoModel from kallithea.model.user import UserModel from kallithea.model.db import Setting log = get_logger(create_repo) DBS = get_session() cur_user = UserModel(DBS)._get_user(cur_user) owner = cur_user repo_name = form_data['repo_name'] repo_name_full = form_data['repo_name_full'] repo_type = form_data['repo_type'] description = form_data['repo_description'] private = form_data['repo_private'] clone_uri = form_data.get('clone_uri') repo_group = form_data['repo_group'] landing_rev = form_data['repo_landing_rev'] copy_fork_permissions = form_data.get('copy_permissions') copy_group_permissions = form_data.get('repo_copy_permissions') fork_of = form_data.get('fork_parent_id') state = form_data.get('repo_state', Repository.STATE_PENDING) # repo creation defaults, private and repo_type are filled in form defs = Setting.get_default_repo_settings(strip_prefix=True) enable_statistics = defs.get('repo_enable_statistics') enable_locking = defs.get('repo_enable_locking') enable_downloads = defs.get('repo_enable_downloads') try: repo = RepoModel(DBS)._create_repo( repo_name=repo_name_full, repo_type=repo_type, description=description, owner=owner, private=private, clone_uri=clone_uri, repo_group=repo_group, landing_rev=landing_rev, fork_of=fork_of, copy_fork_permissions=copy_fork_permissions, copy_group_permissions=copy_group_permissions, enable_statistics=enable_statistics, enable_locking=enable_locking, enable_downloads=enable_downloads, state=state) action_logger(cur_user, 'user_created_repo', form_data['repo_name_full'], '', DBS) DBS.commit() # now create this repo on Filesystem RepoModel(DBS)._create_filesystem_repo( repo_name=repo_name, repo_type=repo_type, repo_group=RepoModel(DBS)._get_repo_group(repo_group), clone_uri=clone_uri, ) repo = Repository.get_by_repo_name(repo_name_full) log_create_repository(repo.get_dict(), created_by=owner.username) # update repo changeset caches initially repo.update_changeset_cache() # set new created state repo.set_state(Repository.STATE_CREATED) DBS.commit() except Exception, e: log.warning('Exception %s occurred when forking repository, ' 'doing cleanup...' % e) # rollback things manually ! repo = Repository.get_by_repo_name(repo_name_full) if repo: Repository.delete(repo.repo_id) DBS.commit() RepoModel(DBS)._delete_filesystem_repo(repo) raise
def archivefile(self, repo_name, fname): fileformat = None revision = None ext = None subrepos = request.GET.get('subrepos') == 'true' for a_type, ext_data in settings.ARCHIVE_SPECS.items(): archive_spec = fname.split(ext_data[1]) if len(archive_spec) == 2 and archive_spec[1] == '': fileformat = a_type or ext_data[1] revision = archive_spec[0] ext = ext_data[1] try: dbrepo = RepoModel().get_by_repo_name(repo_name) if not dbrepo.enable_downloads: return _('Downloads disabled') # TODO: do something else? if c.db_repo_scm_instance.alias == 'hg': # patch and reset hooks section of UI config to not run any # hooks on fetching archives with subrepos for k, v in c.db_repo_scm_instance._repo.ui.configitems( 'hooks'): c.db_repo_scm_instance._repo.ui.setconfig('hooks', k, None) cs = c.db_repo_scm_instance.get_changeset(revision) content_type = settings.ARCHIVE_SPECS[fileformat][0] except ChangesetDoesNotExistError: return _('Unknown revision %s') % revision except EmptyRepositoryError: return _('Empty repository') except (ImproperArchiveTypeError, KeyError): return _('Unknown archive type') from kallithea import CONFIG rev_name = cs.raw_id[:12] archive_name = '%s-%s%s' % (repo_name.replace('/', '_'), rev_name, ext) archive_path = None cached_archive_path = None archive_cache_dir = CONFIG.get('archive_cache_dir') if archive_cache_dir and not subrepos: # TODO: subrepo caching? if not os.path.isdir(archive_cache_dir): os.makedirs(archive_cache_dir) cached_archive_path = os.path.join(archive_cache_dir, archive_name) if os.path.isfile(cached_archive_path): log.debug('Found cached archive in %s', cached_archive_path) archive_path = cached_archive_path else: log.debug('Archive %s is not yet cached', archive_name) if archive_path is None: # generate new archive fd, archive_path = tempfile.mkstemp() log.debug('Creating new temp archive in %s', archive_path) with os.fdopen(fd, 'wb') as stream: cs.fill_archive(stream=stream, kind=fileformat, subrepos=subrepos) # stream (and thus fd) has been closed by cs.fill_archive if cached_archive_path is not None: # we generated the archive - move it to cache log.debug('Storing new archive in %s', cached_archive_path) shutil.move(archive_path, cached_archive_path) archive_path = cached_archive_path def get_chunked_archive(archive_path): stream = open(archive_path, 'rb') while True: data = stream.read(16 * 1024) if not data: break yield data stream.close() if archive_path != cached_archive_path: log.debug('Destroying temp archive %s', archive_path) os.remove(archive_path) action_logger(user=request.authuser, action='user_downloaded_archive:%s' % (archive_name), repo=repo_name, ipaddr=request.ip_addr, commit=True) response.content_disposition = str('attachment; filename=%s' % (archive_name)) response.content_type = str(content_type) return get_chunked_archive(archive_path)
def comment(self, repo_name, pull_request_id): pull_request = PullRequest.get_or_404(pull_request_id) status = 0 close_pr = False allowed_to_change_status = self._get_is_allowed_change_status( pull_request) if allowed_to_change_status: status = request.POST.get('changeset_status') close_pr = request.POST.get('save_close') text = request.POST.get('text', '').strip() or _('No comments.') if close_pr: text = _('Closing.') + '\n' + text comm = ChangesetCommentsModel().create( text=text, repo=c.db_repo.repo_id, user=c.authuser.user_id, pull_request=pull_request_id, f_path=request.POST.get('f_path'), line_no=request.POST.get('line'), status_change=(ChangesetStatus.get_status_lbl(status) if status and allowed_to_change_status else None), closing_pr=close_pr) action_logger(self.authuser, 'user_commented_pull_request:%s' % pull_request_id, c.db_repo, self.ip_addr, self.sa) if allowed_to_change_status: # get status if set ! if status: ChangesetStatusModel().set_status(c.db_repo.repo_id, status, c.authuser.user_id, comm, pull_request=pull_request_id) if close_pr: PullRequestModel().close_pull_request(pull_request_id) action_logger(self.authuser, 'user_closed_pull_request:%s' % pull_request_id, c.db_repo, self.ip_addr, self.sa) Session().commit() if not request.environ.get('HTTP_X_PARTIAL_XHR'): return redirect(pull_request.url()) data = { 'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))), } if comm: c.co = comm data.update(comm.get_dict()) data.update({ 'rendered_text': render('changeset/changeset_comment_block.html') }) return data
def create_cs_pr_comment(repo_name, revision=None, pull_request=None, allowed_to_change_status=True): """ Add a comment to the specified changeset or pull request, using POST values from the request. Comments can be inline (when a file path and line number is specified in POST) or general comments. A comment can be accompanied by a review status change (accepted, rejected, etc.). Pull requests can be closed or deleted. Parameter 'allowed_to_change_status' is used for both status changes and closing of pull requests. For deleting of pull requests, more specific checks are done. """ assert request.environ.get('HTTP_X_PARTIAL_XHR') if pull_request: pull_request_id = pull_request.pull_request_id else: pull_request_id = None status = request.POST.get('changeset_status') close_pr = request.POST.get('save_close') delete = request.POST.get('save_delete') f_path = request.POST.get('f_path') line_no = request.POST.get('line') if (status or close_pr or delete) and (f_path or line_no): # status votes and closing is only possible in general comments raise HTTPBadRequest() if not allowed_to_change_status: if status or close_pr: h.flash(_('No permission to change status'), 'error') raise HTTPForbidden() if pull_request and delete == "delete": if (pull_request.owner_id == request.authuser.user_id or h.HasPermissionAny('hg.admin')() or h.HasRepoPermissionLevel('admin')( pull_request.org_repo.repo_name) or h.HasRepoPermissionLevel('admin')( pull_request.other_repo.repo_name) ) and not pull_request.is_closed(): PullRequestModel().delete(pull_request) Session().commit() h.flash(_('Successfully deleted pull request %s') % pull_request_id, category='success') return { 'location': h.url('my_pullrequests'), # or repo pr list? } raise HTTPForbidden() text = request.POST.get('text', '').strip() comment = ChangesetCommentsModel().create( text=text, repo=c.db_repo.repo_id, author=request.authuser.user_id, revision=revision, pull_request=pull_request_id, f_path=f_path or None, line_no=line_no or None, status_change=ChangesetStatus.get_status_lbl(status) if status else None, closing_pr=close_pr, ) if status: ChangesetStatusModel().set_status( c.db_repo.repo_id, status, request.authuser.user_id, comment, revision=revision, pull_request=pull_request_id, ) if pull_request: action = 'user_commented_pull_request:%s' % pull_request_id else: action = 'user_commented_revision:%s' % revision action_logger(request.authuser, action, c.db_repo, request.ip_addr) if pull_request and close_pr: PullRequestModel().close_pull_request(pull_request_id) action_logger(request.authuser, 'user_closed_pull_request:%s' % pull_request_id, c.db_repo, request.ip_addr) Session().commit() data = { 'target_id': h.safeid(request.POST.get('f_path')), } if comment is not None: c.comment = comment data.update(comment.get_dict()) data.update({ 'rendered_text': render('changeset/changeset_comment_block.html') }) return data
def create_repo(form_data, cur_user): from kallithea.model.repo import RepoModel from kallithea.model.user import UserModel from kallithea.model.db import Setting log = get_logger(create_repo) DBS = get_session() cur_user = UserModel(DBS)._get_user(cur_user) owner = cur_user repo_name = form_data['repo_name'] repo_name_full = form_data['repo_name_full'] repo_type = form_data['repo_type'] description = form_data['repo_description'] private = form_data['repo_private'] clone_uri = form_data.get('clone_uri') repo_group = form_data['repo_group'] landing_rev = form_data['repo_landing_rev'] copy_fork_permissions = form_data.get('copy_permissions') copy_group_permissions = form_data.get('repo_copy_permissions') fork_of = form_data.get('fork_parent_id') state = form_data.get('repo_state', Repository.STATE_PENDING) # repo creation defaults, private and repo_type are filled in form defs = Setting.get_default_repo_settings(strip_prefix=True) enable_statistics = defs.get('repo_enable_statistics') enable_locking = defs.get('repo_enable_locking') enable_downloads = defs.get('repo_enable_downloads') try: repo = RepoModel(DBS)._create_repo( repo_name=repo_name_full, repo_type=repo_type, description=description, owner=owner, private=private, clone_uri=clone_uri, repo_group=repo_group, landing_rev=landing_rev, fork_of=fork_of, copy_fork_permissions=copy_fork_permissions, copy_group_permissions=copy_group_permissions, enable_statistics=enable_statistics, enable_locking=enable_locking, enable_downloads=enable_downloads, state=state ) action_logger(cur_user, 'user_created_repo', form_data['repo_name_full'], '', DBS) DBS.commit() # now create this repo on Filesystem RepoModel(DBS)._create_filesystem_repo( repo_name=repo_name, repo_type=repo_type, repo_group=RepoModel(DBS)._get_repo_group(repo_group), clone_uri=clone_uri, ) repo = Repository.get_by_repo_name(repo_name_full) log_create_repository(repo.get_dict(), created_by=owner.username) # update repo changeset caches initially repo.update_changeset_cache() # set new created state repo.set_state(Repository.STATE_CREATED) DBS.commit() except Exception as e: log.warning('Exception %s occurred when forking repository, ' 'doing cleanup...' % e) # rollback things manually ! repo = Repository.get_by_repo_name(repo_name_full) if repo: Repository.delete(repo.repo_id) DBS.commit() RepoModel(DBS)._delete_filesystem_repo(repo) raise # it's an odd fix to make celery fail task when exception occurs def on_failure(self, *args, **kwargs): pass return True
def comment(self, repo_name, pull_request_id): pull_request = PullRequest.get_or_404(pull_request_id) status = request.POST.get('changeset_status') close_pr = request.POST.get('save_close') delete = request.POST.get('save_delete') f_path = request.POST.get('f_path') line_no = request.POST.get('line') if (status or close_pr or delete) and (f_path or line_no): # status votes and closing is only possible in general comments raise HTTPBadRequest() allowed_to_change_status = self._get_is_allowed_change_status(pull_request) if not allowed_to_change_status: if status or close_pr: h.flash(_('No permission to change pull request status'), 'error') raise HTTPForbidden() if delete == "delete": if (pull_request.owner_id == request.authuser.user_id or h.HasPermissionAny('hg.admin')() or h.HasRepoPermissionLevel('admin')(pull_request.org_repo.repo_name) or h.HasRepoPermissionLevel('admin')(pull_request.other_repo.repo_name) ) and not pull_request.is_closed(): PullRequestModel().delete(pull_request) Session().commit() h.flash(_('Successfully deleted pull request %s') % pull_request_id, category='success') return { 'location': url('my_pullrequests'), # or repo pr list? } raise HTTPFound(location=url('my_pullrequests')) # or repo pr list? raise HTTPForbidden() text = request.POST.get('text', '').strip() comment = create_comment( text, status, pull_request_id=pull_request_id, f_path=f_path, line_no=line_no, closing_pr=close_pr, ) action_logger(request.authuser, 'user_commented_pull_request:%s' % pull_request_id, c.db_repo, request.ip_addr) if status: ChangesetStatusModel().set_status( c.db_repo.repo_id, status, request.authuser.user_id, comment, pull_request=pull_request_id ) if close_pr: PullRequestModel().close_pull_request(pull_request_id) action_logger(request.authuser, 'user_closed_pull_request:%s' % pull_request_id, c.db_repo, request.ip_addr) Session().commit() if not request.environ.get('HTTP_X_PARTIAL_XHR'): raise HTTPFound(location=pull_request.url()) data = { 'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))), } if comment is not None: c.comment = comment data.update(comment.get_dict()) data.update({'rendered_text': render('changeset/changeset_comment_block.html')}) return data
def archivefile(self, repo_name, fname): fileformat = None revision = None ext = None subrepos = request.GET.get('subrepos') == 'true' for a_type, ext_data in settings.ARCHIVE_SPECS.items(): archive_spec = fname.split(ext_data[1]) if len(archive_spec) == 2 and archive_spec[1] == '': fileformat = a_type or ext_data[1] revision = archive_spec[0] ext = ext_data[1] try: dbrepo = RepoModel().get_by_repo_name(repo_name) if not dbrepo.enable_downloads: return _('Downloads disabled') if c.db_repo_scm_instance.alias == 'hg': # patch and reset hooks section of UI config to not run any # hooks on fetching archives with subrepos for k, v in c.db_repo_scm_instance._repo.ui.configitems('hooks'): c.db_repo_scm_instance._repo.ui.setconfig('hooks', k, None) cs = c.db_repo_scm_instance.get_changeset(revision) content_type = settings.ARCHIVE_SPECS[fileformat][0] except ChangesetDoesNotExistError: return _('Unknown revision %s') % revision except EmptyRepositoryError: return _('Empty repository') except (ImproperArchiveTypeError, KeyError): return _('Unknown archive type') # archive cache from kallithea import CONFIG rev_name = cs.raw_id[:12] archive_name = '%s-%s%s' % (safe_str(repo_name.replace('/', '_')), safe_str(rev_name), ext) use_cached_archive = False # defines if we use cached version of archive archive_cache_enabled = CONFIG.get('archive_cache_dir') if not subrepos and archive_cache_enabled: #check if we it's ok to write if not os.path.isdir(CONFIG['archive_cache_dir']): os.makedirs(CONFIG['archive_cache_dir']) cached_archive_path = os.path.join(CONFIG['archive_cache_dir'], archive_name) if os.path.isfile(cached_archive_path): log.debug('Found cached archive in %s' % cached_archive_path) fd, archive = None, cached_archive_path use_cached_archive = True else: log.debug('Archive %s is not yet cached' % (archive_name)) if not use_cached_archive: # generate new archive fd, archive = tempfile.mkstemp() temp_stream = open(archive, 'wb') log.debug('Creating new temp archive in %s' % archive) cs.fill_archive(stream=temp_stream, kind=fileformat, subrepos=subrepos) temp_stream.close() if not subrepos and archive_cache_enabled: #if we generated the archive and use cache rename that log.debug('Storing new archive in %s' % cached_archive_path) shutil.move(archive, cached_archive_path) archive = cached_archive_path def get_chunked_archive(archive): stream = open(archive, 'rb') while True: data = stream.read(16 * 1024) if not data: stream.close() if fd: # fd means we used temporary file os.close(fd) if not archive_cache_enabled: log.debug('Destroying temp archive %s' % archive) os.remove(archive) break yield data # store download action action_logger(user=c.authuser, action='user_downloaded_archive:%s' % (archive_name), repo=repo_name, ipaddr=self.ip_addr, commit=True) response.content_disposition = str('attachment; filename=%s' % (archive_name)) response.content_type = str(content_type) return get_chunked_archive(archive)
def comment(self, repo_name, pull_request_id): pull_request = PullRequest.get_or_404(pull_request_id) status = request.POST.get('changeset_status') close_pr = request.POST.get('save_close') delete = request.POST.get('save_delete') f_path = request.POST.get('f_path') line_no = request.POST.get('line') if (status or close_pr or delete) and (f_path or line_no): # status votes and closing is only possible in general comments raise HTTPBadRequest() allowed_to_change_status = self._get_is_allowed_change_status(pull_request) if not allowed_to_change_status: if status or close_pr: h.flash(_('No permission to change pull request status'), 'error') raise HTTPForbidden() if delete == "delete": if (pull_request.owner.user_id == c.authuser.user_id or h.HasPermissionAny('hg.admin')() or h.HasRepoPermissionAny('repository.admin')(pull_request.org_repo.repo_name) or h.HasRepoPermissionAny('repository.admin')(pull_request.other_repo.repo_name) ) and not pull_request.is_closed(): PullRequestModel().delete(pull_request) Session().commit() h.flash(_('Successfully deleted pull request %s') % pull_request_id, category='success') return { 'location': url('my_pullrequests'), # or repo pr list? } raise HTTPFound(location=url('my_pullrequests')) # or repo pr list? raise HTTPForbidden() text = request.POST.get('text', '').strip() if close_pr: text = _('Closing.') + '\n' + text comment = create_comment( text, status, pull_request_id=pull_request_id, f_path=f_path, line_no=line_no, closing_pr=close_pr, ) action_logger(self.authuser, 'user_commented_pull_request:%s' % pull_request_id, c.db_repo, self.ip_addr, self.sa) if status: ChangesetStatusModel().set_status( c.db_repo.repo_id, status, c.authuser.user_id, comment, pull_request=pull_request_id ) if close_pr: PullRequestModel().close_pull_request(pull_request_id) action_logger(self.authuser, 'user_closed_pull_request:%s' % pull_request_id, c.db_repo, self.ip_addr, self.sa) Session().commit() if not request.environ.get('HTTP_X_PARTIAL_XHR'): raise HTTPFound(location=pull_request.url()) data = { 'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))), } if comment is not None: c.comment = comment data.update(comment.get_dict()) data.update({'rendered_text': render('changeset/changeset_comment_block.html')}) return data