def update_perm(self, id): """PUT /users_perm/id: Update an existing item""" # url('user_perm', id=ID, method='put') grant_perm = request.POST.get('create_repo_perm', False) user_model = UserModel() if grant_perm: perm = Permission.get_by_key('hg.create.none') user_model.revoke_perm(id, perm) perm = Permission.get_by_key('hg.create.repository') user_model.grant_perm(id, perm) h.flash(_("Granted 'repository create' permission to user"), category='success') Session.commit() else: perm = Permission.get_by_key('hg.create.repository') user_model.revoke_perm(id, perm) perm = Permission.get_by_key('hg.create.none') user_model.grant_perm(id, perm) h.flash(_("Revoked 'repository create' permission to user"), category='success') Session.commit() return redirect(url('edit_user', id=id))
def _ignorews_url(GET, fileid=None): fileid = str(fileid) if fileid else None params = defaultdict(list) _update_with_GET(params, GET) lbl = _('show white space') ig_ws = get_ignore_ws(fileid, GET) ln_ctx = get_line_ctx(fileid, GET) # global option if fileid is None: if ig_ws is None: params['ignorews'] += [1] lbl = _('ignore white space') ctx_key = 'context' ctx_val = ln_ctx # per file options else: if ig_ws is None: params[fileid] += ['WS:1'] lbl = _('ignore white space') ctx_key = fileid ctx_val = 'C:%s' % ln_ctx # if we have passed in ln_ctx pass it along to our params if ln_ctx: params[ctx_key] += [ctx_val] params['anchor'] = fileid img = h.image(h.url('/images/icons/text_strikethrough.png'), lbl, class_='icon') return h.link_to(img, h.url.current(**params), title=lbl, class_='tooltip')
def _get_node_history(self, cs, f_path, changesets=None): if changesets is None: changesets = cs.get_file_history(f_path) hist_l = [] changesets_group = ([], _("Changesets")) branches_group = ([], _("Branches")) tags_group = ([], _("Tags")) _hg = cs.repository.alias == 'hg' for chs in changesets: _branch = '(%s)' % chs.branch if _hg else '' n_desc = 'r%s:%s %s' % (chs.revision, chs.short_id, _branch) changesets_group[0].append((chs.raw_id, n_desc,)) hist_l.append(changesets_group) for name, chs in c.rhodecode_repo.branches.items(): branches_group[0].append((chs, name),) hist_l.append(branches_group) for name, chs in c.rhodecode_repo.tags.items(): tags_group[0].append((chs, name),) hist_l.append(tags_group) return hist_l
def pwchange(self, userid): """Reset a user password""" user = self._get_user(userid) if not user: abort(404) c.form = ChangePasswordForm(request.POST, csrf_context=session) if request.POST and c.form.validate(): if user.local and not user.is_superadmin: user.set_password(c.form.password1.data) Session.add(user) Session.commit() flash(_('The account password for %(name)s has been reset') % dict(name=user.username)) info = PASSWORDCHANGE_MSG % dict(u=user.username) audit_log(c.user.username, 2, unicode(info), request.host, request.remote_addr, now()) else: if user.is_superadmin: flash(_('Admin accounts can not be modified via the web')) else: flash(_('This is an external account, use' ' external system to reset the password')) redirect(url('account-detail', userid=user.id)) c.id = userid c.username = user.username c.posturl = 'accounts-pw-change' return render('/accounts/pwchange.html')
def repo_refs_data(self, repo_name): repo = Repository.get_by_repo_name(repo_name).scm_instance res = [] _branches = repo.branches.items() if _branches: res.append({ 'text': _('Branch'), 'children': [{'id': rev, 'text': name, 'type': 'branch'} for name, rev in _branches] }) _tags = repo.tags.items() if _tags: res.append({ 'text': _('Tag'), 'children': [{'id': rev, 'text': name, 'type': 'tag'} for name, rev in _tags] }) _bookmarks = repo.bookmarks.items() if _bookmarks: res.append({ 'text': _('Bookmark'), 'children': [{'id': rev, 'text': name, 'type': 'book'} for name, rev in _bookmarks] }) data = { 'more': False, 'results': res } return data
def repo_public_journal(self, repo_name): """ Set's this repository to be visible in public journal, in other words assing default user to follow this repo :param repo_name: """ cur_token = request.POST.get('auth_token') token = get_token() if cur_token == token: try: repo_id = Repository.get_by_repo_name(repo_name).repo_id user_id = User.get_by_username('default').user_id self.scm_model.toggle_following_repo(repo_id, user_id) h.flash(_('Updated repository visibility in public journal'), category='success') Session.commit() except: h.flash(_('An error occurred during setting this' ' repository in public journal'), category='error') else: h.flash(_('Token mismatch'), category='error') return redirect(url('edit_repo', repo_name=repo_name))
def getClassInfo(cls, key=None, ret='all'): ''' getClassInfo - returns all or a subtree of the token definition :param key: subsection identifier :type key: string :param ret: default return value, if nothing is found :type ret: user defined :return: subsection if key exists or user defined :rtype : s.o. ''' res = { 'type' : 'vasco', 'title' : _('Vasco Token'), 'description' : _('Vasco Digipass Token Class - proprietary timebased tokens'), 'init' : {}, 'config' : {}, 'selfservice' : {}, } if key is not None and res.has_key(key): ret = res.get(key) else: if ret == 'all': ret = res return ret
def new(self): """Render new record form and redirect to save.""" flash_message(_("success message"), "success") flash_message(_("warning message"), "warning") flash_message(_("error message"), "error") flash_message(_("notice message"), "notice") return render('/derived/rock/new.mako')
def upwchange(self, userid): """User change own password""" user = self._get_user(userid) if not user: abort(404) if user.id != c.user.id or c.user.is_superadmin: abort(403) c.form = UserPasswordForm(request.POST, csrf_context=session) if (request.POST and c.form.validate() and user.validate_password(c.form.password3.data)): if user.local: user.set_password(c.form.password1.data) Session.add(user) Session.commit() flash(_('The account password for %(name)s has been reset') % dict(name=user.username)) info = PASSWORDCHANGE_MSG % dict(u=user.username) audit_log(c.user.username, 2, unicode(info), request.host, request.remote_addr, now()) else: flash(_('This is an external account, use' ' external system to reset the password')) redirect(url('account-detail', userid=user.id)) elif (request.POST and not user.validate_password(c.form.password3.data) and not c.form.password3.errors): flash_alert(_('The old password supplied does' ' not match our records')) c.id = userid c.username = user.username c.posturl = 'accounts-pw-uchange' return render('/accounts/pwchange.html')
def comment(self, repo_name, revision): status = request.POST.get('changeset_status') change_status = request.POST.get('change_changeset_status') text = request.POST.get('text') if status and change_status: text = text or (_('Status change -> %s') % ChangesetStatus.get_status_lbl(status)) c.co = comm = ChangesetCommentsModel().create( text=text, repo=c.rhodecode_db_repo.repo_id, user=c.rhodecode_user.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 and change_status else None) ) # get status if set ! if status and change_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.rhodecode_db_repo.repo_id, status, c.rhodecode_user.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.rhodecode_user, 'user_commented_revision:%s' % revision, c.rhodecode_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 _get_node_history(self, cs, f_path): changesets = cs.get_file_history(f_path) hist_l = [] changesets_group = ([], _("Changesets")) branches_group = ([], _("Branches")) tags_group = ([], _("Tags")) for chs in changesets: n_desc = 'r%s:%s' % (chs.revision, chs.short_id) changesets_group[0].append((chs.raw_id, n_desc,)) hist_l.append(changesets_group) for name, chs in c.rhodecode_repo.branches.items(): #chs = chs.split(':')[-1] branches_group[0].append((chs, name),) hist_l.append(branches_group) for name, chs in c.rhodecode_repo.tags.items(): #chs = chs.split(':')[-1] tags_group[0].append((chs, name),) hist_l.append(tags_group) return hist_l
def delete(self, user, cur_user=None): if not cur_user: cur_user = getattr(get_current_authuser(), 'username', None) user = self._get_user(user) if user.username == User.DEFAULT_USER: raise DefaultUserException( _(u"You can't remove this user since it's" " crucial for entire application") ) if user.repositories: repos = [x.repo_name for x in user.repositories] raise UserOwnsReposException( _(u'User "%s" still owns %s repositories and cannot be ' 'removed. Switch owners or remove those repositories: %s') % (user.username, len(repos), ', '.join(repos)) ) if user.repo_groups: repogroups = [x.group_name for x in user.repo_groups] raise UserOwnsReposException( _(u'User "%s" still owns %s repository groups and cannot be ' 'removed. Switch owners or remove those repository groups: %s') % (user.username, len(repogroups), ', '.join(repogroups)) ) if user.user_groups: usergroups = [x.users_group_name for x in user.user_groups] raise UserOwnsReposException( _(u'User "%s" still owns %s user groups and cannot be ' 'removed. Switch owners or remove those user groups: %s') % (user.username, len(usergroups), ', '.join(usergroups)) ) self.sa.delete(user) from kallithea.lib.hooks import log_delete_user log_delete_user(user.get_dict(), cur_user)
def enqueue(self): try: data = json.load(request.environ['wsgi.input']) except ValueError: log.error('ENQUEUE: Could not parse JSON data') abort(400, _('Malformed JSON data')) files = data.get('files') if not (files and len(files) > 0): log.error('ENQUEUE: No files specified') abort(400, _('No files specified')) jukebox = Jukebox() for file in files: if not file: log.error('ENQUEUE: Skipping empty file') abort(400, _('Missing file name')) try: jukebox.queue(file.encode('utf8')) except QueueFull: log.error('ENQUEUE: Full, aborting') response.status = "409 %s" % _('The queue is full') return abort(204) # no content
def delete(self, userid): """/accounts/delete/id""" user = self._get_user(userid) if not user: abort(404) c.form = EditUserForm(request.POST, user, csrf_context=session) del c.form.domains if request.POST and c.form.validate(): username = user.username user_id = unicode(user.id) Session.delete(user) Session.commit() update_serial.delay() flash(_('The account has been deleted')) info = DELETEACCOUNT_MSG % dict(u=username) audit_log(c.user.username, 4, unicode(info), request.host, request.remote_addr, now()) if userid == user_id: redirect(url('/logout')) redirect(url(controller='accounts', action='index')) else: flash_info(_('The account: %(a)s and all associated data' ' will be deleted, This action is not reversible.') % dict(a=user.username)) c.fields = FORM_FIELDS c.id = userid return render('/accounts/delete.html')
def ldap_settings(self): """POST ldap create and store ldap settings""" _form = LdapSettingsForm([x[0] for x in self.tls_reqcert_choices], [x[0] for x in self.search_scope_choices], [x[0] for x in self.tls_kind_choices])() try: form_result = _form.to_python(dict(request.POST)) try: for k, v in form_result.items(): if k.startswith('ldap_'): setting = RhodeCodeSettings.get_by_name(k) setting.app_settings_value = v self.sa.add(setting) self.sa.commit() h.flash(_('Ldap settings updated successfully'), category='success') except (DatabaseError,): raise except LdapImportError: h.flash(_('Unable to activate ldap. The "python-ldap" library ' 'is missing.'), category='warning') except formencode.Invalid, errors: e = errors.error_dict or {} return htmlfill.render( render('admin/ldap/ldap.html'), defaults=errors.value, errors=e, prefix_error=False, encoding="UTF-8")
def delete_perms(self, id): """ DELETE an existing repository group permission user :param group_name: """ try: obj_type = request.POST.get('obj_type') obj_id = None if obj_type == 'user': obj_id = safe_int(request.POST.get('user_id')) elif obj_type == 'user_group': obj_id = safe_int(request.POST.get('user_group_id')) if not c.authuser.is_admin: if obj_type == 'user' and c.authuser.user_id == obj_id: msg = _('Cannot revoke permission for yourself as admin') h.flash(msg, category='warning') raise Exception('revoke admin permission on self') if obj_type == 'user': UserGroupModel().revoke_user_permission(user_group=id, user=obj_id) elif obj_type == 'user_group': UserGroupModel().revoke_user_group_permission(target_user_group=id, user_group=obj_id) Session().commit() except Exception: log.error(traceback.format_exc()) h.flash(_('An error occurred during revoking of permission'), category='error') raise HTTPInternalServerError()
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 doEdit(self): member = self.lmf.getUser(session['identity']) try: language = Session.query(Preferences).filter(and_(Preferences.uidNumber == member.uidNumber, Preferences.key == 'language')).one() language.last_change = datetime.now() language.value = request.params['language'] session['language'] = language.value session['flash'] = _('Changes saved!') session['flash_class'] = 'success' except NoResultFound: pref = Preferences() pref.uidNumber = member.uidNumber pref.last_change = datetime.now().date() pref.key = 'language' pref.value = request.params['language'] Session.add(pref) session['language'] = request.params['language'] session['flash'] = _('Changes saved!') session['flash_class'] = 'success' except: session['flash'] = _('Unknown error, nothing saved') session['flash_class'] = 'error' Session.commit() session.save() redirect(url(controller='preferences', action='edit'))
def make_description(self, notification, show_age=True): """ Creates a human readable description based on properties of notification object """ _map = { notification.TYPE_CHANGESET_COMMENT: _('commented on commit'), notification.TYPE_MESSAGE: _('sent message'), notification.TYPE_MENTION: _('mentioned you'), notification.TYPE_REGISTRATION: _('registered in RhodeCode') } tmpl = "%(user)s %(action)s %(when)s" if show_age: when = h.age(notification.created_on) else: DTF = lambda d: datetime.datetime.strftime(d, DATETIME_FORMAT) when = DTF(notification.created_on) data = dict( user=notification.created_by_user.username, action=_map[notification.type_], when=when, ) return tmpl % data
def lnk(rev, repo_name): if isinstance(rev, BaseChangeset) or isinstance(rev, AttributeDict): lazy_cs = True if getattr(rev, 'op', None) and getattr(rev, 'ref_name', None): lazy_cs = False lbl = '?' if rev.op == 'delete_branch': lbl = '%s' % _('Deleted branch: %s') % rev.ref_name title = '' elif rev.op == 'tag': lbl = '%s' % _('Created tag: %s') % rev.ref_name title = '' _url = '#' else: lbl = '%s' % (rev.short_id[:8]) _url = url('changeset_home', repo_name=repo_name, revision=rev.raw_id) title = tooltip(rev.message) else: ## changeset cannot be found/striped/removed etc. lbl = ('%s' % rev)[:12] _url = '#' title = _('Changeset not found') if parse_cs: return link_to(lbl, _url, title=title, class_='tooltip') return link_to(lbl, _url, raw_id=rev.raw_id, repo_name=repo_name, class_='lazy-cs' if lazy_cs else '')
def repo_check(self, repo_name): c.repo = repo_name task_id = request.GET.get('task_id') if task_id and task_id not in ['None']: from kallithea import CELERY_ON from celery.result import AsyncResult if CELERY_ON: task = AsyncResult(task_id) if task.failed(): raise HTTPInternalServerError(task.traceback) repo = Repository.get_by_repo_name(repo_name) if repo and repo.repo_state == Repository.STATE_CREATED: if repo.clone_uri: clone_uri = repo.clone_uri_hidden h.flash(_('Created repository %s from %s') % (repo.repo_name, clone_uri), category='success') else: repo_url = h.link_to(repo.repo_name, h.url('summary_home', repo_name=repo.repo_name)) fork = repo.fork if fork: fork_name = fork.repo_name h.flash(h.literal(_('Forked repository %s as %s') % (fork_name, repo_url)), category='success') else: h.flash(h.literal(_('Created repository %s') % repo_url), category='success') return {'result': True} return {'result': False}
def password_reset(self): settings = Setting.get_app_settings() captcha_private_key = settings.get('captcha_private_key') c.captcha_active = bool(captcha_private_key) c.captcha_public_key = settings.get('captcha_public_key') if request.POST: password_reset_form = PasswordResetForm()() try: form_result = password_reset_form.to_python(dict(request.POST)) if c.captcha_active: from kallithea.lib.recaptcha import submit response = submit(request.POST.get('recaptcha_challenge_field'), request.POST.get('recaptcha_response_field'), private_key=captcha_private_key, remoteip=self.ip_addr) if c.captcha_active and not response.is_valid: _value = form_result _msg = _('bad captcha') error_dict = {'recaptcha_field': _msg} raise formencode.Invalid(_msg, _value, None, error_dict=error_dict) UserModel().reset_password_link(form_result) h.flash(_('Your password reset link was sent'), category='success') return redirect(url('login_home')) except formencode.Invalid, errors: return htmlfill.render( render('/password_reset.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8", force_defaults=False)
def delete(self, user, cur_user=None): if not cur_user: cur_user = getattr(get_current_rhodecode_user(), "username", None) user = self._get_user(user) try: if user.username == "default": raise DefaultUserException( _(u"You can't remove this user since it's" " crucial for entire application") ) if user.repositories: repos = [x.repo_name for x in user.repositories] raise UserOwnsReposException( _( u'user "%s" still owns %s repositories and cannot be ' "removed. Switch owners or remove those repositories. %s" ) % (user.username, len(repos), ", ".join(repos)) ) self.sa.delete(user) from rhodecode.lib.hooks import log_delete_user log_delete_user(user.get_dict(), cur_user) except Exception: log.error(traceback.format_exc()) raise
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_settings_delete', repo_name=ID), # method='delete') # url('repo_settings_delete', 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('home')) try: action_logger(self.rhodecode_user, 'user_deleted_repo', repo_name, self.ip_addr, self.sa) repo_model.delete(repo) invalidate_cache('get_repo_cached_%s' % repo_name) h.flash(_('deleted repository %s') % repo_name, category='success') Session().commit() except Exception: log.error(traceback.format_exc()) h.flash(_('An error occurred during deletion of %s') % repo_name, category='error') return redirect(url('admin_settings_my_account', anchor='my'))
def get_repo_landing_revs(self, repo=None): """ Generates select option with tags branches and bookmarks (for hg only) grouped by type :param repo: """ hist_l = [] choices = [] repo = self.__get_repo(repo) hist_l.append(['tip', _('latest tip')]) choices.append('tip') if not repo: return choices, hist_l repo = repo.scm_instance branches_group = ([(k, k) for k, v in repo.branches.iteritems()], _("Branches")) hist_l.append(branches_group) choices.extend([x[0] for x in branches_group[0]]) if repo.alias == 'hg': bookmarks_group = ([(k, k) for k, v in repo.bookmarks.iteritems()], _("Bookmarks")) hist_l.append(bookmarks_group) choices.extend([x[0] for x in bookmarks_group[0]]) tags_group = ([(k, k) for k, v in repo.tags.iteritems()], _("Tags")) hist_l.append(tags_group) choices.extend([x[0] for x in tags_group[0]]) return choices, hist_l
def edit(self, gist_id, format='html'): """GET /admin/gists/gist_id/edit: Form to edit an existing item""" # url('edit_gist', gist_id=ID) c.gist = Gist.get_or_404(gist_id) #check if this gist is not expired if c.gist.gist_expires != -1: if time.time() > c.gist.gist_expires: log.error('Gist expired at %s', time_to_datetime(c.gist.gist_expires)) raise HTTPNotFound() try: c.file_changeset, c.files = GistModel().get_gist_files(gist_id) except VCSError: log.error(traceback.format_exc()) raise HTTPNotFound() self.__load_defaults(extra_values=('0', _('Unmodified'))) rendered = render('admin/gists/edit.html') if request.POST: rpost = request.POST nodes = {} for org_filename, filename, mimetype, content in zip( rpost.getall('org_files'), rpost.getall('files'), rpost.getall('mimetypes'), rpost.getall('contents')): nodes[org_filename] = { 'org_filename': org_filename, 'filename': filename, 'content': content, 'lexer': mimetype, } try: GistModel().update( gist=c.gist, description=rpost['description'], owner=c.gist.owner, gist_mapping=nodes, gist_type=c.gist.gist_type, lifetime=rpost['lifetime'] ) Session().commit() h.flash(_('Successfully updated gist content'), category='success') except NodeNotChangedError: # raised if nothing was changed in repo itself. We anyway then # store only DB stuff for gist Session().commit() h.flash(_('Successfully updated gist data'), category='success') except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred during update of gist %s') % gist_id, category='error') raise HTTPFound(location=url('gist', gist_id=gist_id)) return rendered
def delete(self, group_name): """DELETE /repos_groups/group_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('repos_group', group_name=GROUP_NAME), # method='delete') # url('repos_group', group_name=GROUP_NAME) gr = c.repos_group = ReposGroupModel()._get_repo_group(group_name) repos = gr.repositories.all() if repos: h.flash(_('This group contains %s repositores and cannot be ' 'deleted') % len(repos), category='warning') return redirect(url('repos_groups')) children = gr.children.all() if children: h.flash(_('This group contains %s subgroups and cannot be deleted' % (len(children))), category='warning') return redirect(url('repos_groups')) try: ReposGroupModel().delete(group_name) Session().commit() h.flash(_('Removed repository group %s') % group_name, category='success') #TODO: in future action_logger(, '', '', '', self.sa) except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred during deletion of repository group %s') % group_name, category='error') return redirect(url('repos_groups'))
def ip_details(ipaddr): "Return IP type and country for an IP address" try: country_code = '' country_name = '' hostname = '' iptype = IP(ipaddr).iptype() if (iptype != "LOOPBACK" and ipaddr != '127.0.0.1' and iptype != "LINKLOCAL"): socket.setdefaulttimeout(60) #hostname = socket.gethostbyaddr(ipaddr)[0] hostname = get_hostname(ipaddr) if iptype != "PRIVATE": country_name, country_code = geoip_lookup(ipaddr) elif iptype == "LINKLOCAL": hostname = _('IPv6 Link local address') except (socket.gaierror, socket.timeout, socket.error, ValueError): if 'iptype' in locals() and iptype == "PRIVATE": hostname = _("RFC1918 Private address") else: hostname = _("Reverse lookup failed") finally: details = dict(ip_address=ipaddr, hostname=hostname or literal('unknown'), country_code=country_code or 'unknown', country_name=country_name or '', media_url=media_url()) return details
def update_perms(self, group_name): """ Update permissions for given repository group :param group_name: """ c.repo_group = RepoGroupModel()._get_repo_group(group_name) valid_recursive_choices = ['none', 'repos', 'groups', 'all'] form_result = RepoGroupPermsForm(valid_recursive_choices)().to_python(request.POST) if not c.authuser.is_admin: if self._revoke_perms_on_yourself(form_result): msg = _('Cannot revoke permission for yourself as admin') h.flash(msg, category='warning') return redirect(url('edit_repo_group_perms', group_name=group_name)) recursive = form_result['recursive'] # iterate over all members(if in recursive mode) of this groups and # set the permissions ! # this can be potentially heavy operation RepoGroupModel()._update_permissions(c.repo_group, form_result['perms_new'], form_result['perms_updates'], recursive) #TODO: implement this #action_logger(self.authuser, 'admin_changed_repo_permissions', # repo_name, self.ip_addr, self.sa) Session().commit() h.flash(_('Repository Group permissions updated'), category='success') return redirect(url('edit_repo_group_perms', group_name=group_name))
def getInitDetail(self, params , user=None): ''' to complete the token normalisation, the response of the initialiastion should be build by the token specific method, the getInitDetails ''' response_detail = {} info = self.getInfo() response_detail.update(info) response_detail['serial'] = self.getSerial() tok_type = self.type.lower() otpkey = None if 'otpkey' in info: otpkey = info.get('otpkey') if otpkey != None: response_detail["otpkey"] = { "order" : '1', "description": _("OTP seed"), "value" : "seed://%s" % otpkey, "img" : create_img(otpkey, width=200), } try: p = {} p.update(params) p['otpkey'] = otpkey p['serial'] = self.getSerial() # label goo_url = create_google_authenticator(p, user=user, context=self.context) response_detail["googleurl"] = { "order" : '0', "description": _("OTPAuth Url"), "value" : goo_url, "img" : create_img(goo_url, width=250) } except NoOtpAuthTokenException as exx: log.warning("%r" % exx) if user is not None: try: oath_url = create_oathtoken_url(user.login, user.realm, otpkey, tok_type, serial=self.getSerial(), context=self.context) response_detail["oathurl"] = { "order" : '2', "description" : _("URL for OATH token"), "value" : oath_url, "img" : create_img(oath_url, width=250) } except Exception as ex: log.info('failed to set oath or google url: %r' % ex) return response_detail
def delete_api_key(self, id): c.user = User.get_or_404(id) if c.user.username == User.DEFAULT_USER: h.flash(_("You can't edit this user"), category='warning') return redirect(url('users')) api_key = request.POST.get('del_api_key') if request.POST.get('del_api_key_builtin'): user = User.get(c.user.user_id) if user: user.api_key = generate_api_key(user.username) Session().add(user) Session().commit() h.flash(_("Api key successfully reset"), category='success') elif api_key: ApiKeyModel().delete(api_key, c.user.user_id) Session().commit() h.flash(_("Api key successfully deleted"), category='success') return redirect(url('edit_user_api_keys', id=c.user.user_id))
def update_audit_log(username, category, info, hostname, remoteip, timestamp=None): "Update the audit log" logger = update_audit_log.get_logger() try: entry = AuditLog(username, category, info, hostname, remoteip) if timestamp: entry.timestamp = timestamp Session.add(entry) Session.commit() logger.info( _("Audit Log update for: %s from: %s") % (username, remoteip)) except DatabaseError, err: logger.error( _("Audit Log FAILURE: %s %s %s %s %s %s Error: %s") % (username, category, info, hostname, remoteip, timestamp, err))
def delete(self, filterid, format=None): "Delete a temp filter" filters = session.get('filter_by', []) errors = {} success = True try: del filters[int(filterid)] except IndexError: msg = _("The filter does not exist") if format != 'json': flash_alert(msg) errors = dict(msg=msg) success = False if format == 'json': response.headers['Content-Type'] = JSON_HEADER if not errors: self.invalidate = True return json.dumps(self._get_data(format, success, errors)) flash(_("The filter has been removed")) redirect(url(controller='reports'))
class _validator(formencode.validators.FancyValidator): messages = { 'badFormat': _( u'Key name can only consist of letters, ' u'underscore, dash or numbers'), } def validate_python(self, value, state): if not re.match('[a-zA-Z0-9_-]+$', value): raise formencode.Invalid(self.message('badFormat', state), value, state)
def get_error_explanation(self, code): ''' get the error explanations of int codes [400, 401, 403, 404, 500]''' try: code = int(code) except: code = 500 if code == 400: return _('The request could not be understood by the server' ' due to malformed syntax.') if code == 401: return _('Unauthorized access to resource') if code == 403: return _("You don't have permission to view this page") if code == 404: return _('The resource could not be found') if code == 500: return _('The server encountered an unexpected condition' ' which prevented it from fulfilling the request.')
class _validator(formencode.validators.FancyValidator): messages = { 'invalid_path': _(u'This is not a valid path') } def validate_python(self, value, state): if not os.path.isdir(value): msg = M(self, 'invalid_path', state) raise formencode.Invalid(msg, value, state, error_dict=dict(paths_root_path=msg) )
class _validator(formencode.validators.FancyValidator): messages = { 'invalid_fork_type': _(u'Fork have to be the same type as parent') } def validate_python(self, value, state): if old_data['repo_type'] != value: msg = M(self, 'invalid_fork_type', state) raise formencode.Invalid(msg, value, state, error_dict=dict(repo_type=msg) )
def edit_advanced_locking(self, repo_name): """ Unlock repository when it is locked ! :param repo_name: """ try: repo = Repository.get_by_repo_name(repo_name) if request.POST.get('set_lock'): Repository.lock(repo, c.rhodecode_user.user_id, lock_reason=Repository.LOCK_WEB) h.flash(_('Locked repository'), category='success') elif request.POST.get('set_unlock'): Repository.unlock(repo) h.flash(_('Unlocked repository'), category='success') except Exception as e: log.exception("Exception during unlocking") h.flash(_('An error occurred during unlocking'), category='error') return redirect(url('edit_repo_advanced', repo_name=repo_name))
def edit_perms_summary(self, user_id): user_id = safe_int(user_id) c.user = User.get_or_404(user_id) if c.user.username == User.DEFAULT_USER: h.flash(_("You can't edit this user"), category='warning') return redirect(url('users')) c.active = 'perms_summary' c.perm_user = AuthUser(user_id=user_id, ip_addr=self.ip_addr) return render('admin/users/user_edit.html')
class _validator(formencode.validators.FancyValidator): messages = {'invalid_password': _(u'Invalid old password')} def validate_python(self, value, state): from kallithea.lib import auth_modules if not auth_modules.authenticate(username, value, ''): msg = M(self, 'invalid_password', state) raise formencode.Invalid(msg, value, state, error_dict=dict(current_password=msg))
def _get_ref_rev(repo, ref_type, ref_name, returnempty=False): """ Safe way to get changeset. If error occurs show error. """ from kallithea.lib import helpers as h try: return repo.scm_instance.get_ref_revision(ref_type, ref_name) except EmptyRepositoryError as e: if returnempty: return repo.scm_instance.EMPTY_CHANGESET h.flash(h.literal(_('There are no changesets yet')), category='error') raise webob.exc.HTTPNotFound() except ChangesetDoesNotExistError as e: h.flash(h.literal(_('Changeset not found')), category='error') raise webob.exc.HTTPNotFound() except RepositoryError as e: log.error(traceback.format_exc()) h.flash(safe_str(e), category='error') raise webob.exc.HTTPBadRequest()
def verify_volume(lic_dict): # get the current number of active tokens num = getTokenNumResolver() try: token_volume = int(lic_dict.get('token-num', 0)) except TypeError as err: log.error("failed to convert license token num value:%r :%r" % (lic_dict.get('token-num'), err)) return False, "max %d" % token_volume if num > token_volume: log.error("licensed token volume exceeded %r>%r" % (num, token_volume)) used = _("tokens used") licnu = _("tokens supported") detail = " %s: %d > %s: %d" % (used, num, licnu, token_volume) return False, detail return True, ""
def delete(self, orgid): "Delete an organization" org = get_org(orgid) if not org: abort(404) c.id = org.id c.form = org_delete_form(request.POST, session, org) if request.method == 'POST' and c.form.validate(): delete_org(c.form, org, c.user, request.host, request.remote_addr) msg = _('The organization has been deleted') flash(msg) log.info(msg) redirect(url(controller='organizations')) else: msg = _('The organization: %(s)s will be deleted,' ' This action is not reversible') % dict(s=org.name) flash(msg) log.info(msg) return self.render('/organizations/delete.html')
def unboom_content(content, member, delay_commit=False): boom = has_boomed(content, member) if boom: Session.delete(boom) else: raise action_error(_( "%s has not boomed previously boomed this _content" % member), code=400) if not delay_commit: Session.commit()
class ChangelogController(BaseRepoController): @LoginRequired() @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', 'repository.admin') def __before__(self): super(ChangelogController, self).__before__() c.affected_files_cut_off = 60 def index(self): limit = 100 default = 20 if request.params.get('size'): try: int_size = int(request.params.get('size')) except ValueError: int_size = default int_size = int_size if int_size <= limit else limit c.size = int_size session['changelog_size'] = c.size session.save() else: c.size = int(session.get('changelog_size', default)) p = int(request.params.get('page', 1)) branch_name = request.params.get('branch', None) try: if branch_name: collection = [z for z in c.rhodecode_repo.get_changesets(start=0, branch_name=branch_name)] c.total_cs = len(collection) else: collection = c.rhodecode_repo c.total_cs = len(c.rhodecode_repo) c.pagination = RepoPage(collection, page=p, item_count=c.total_cs, items_per_page=c.size, branch=branch_name) collection = list(c.pagination) page_revisions = [x.raw_id for x in collection] c.comments = c.rhodecode_db_repo.comments(page_revisions) except (RepositoryError, ChangesetDoesNotExistError, Exception), e: log.error(traceback.format_exc()) h.flash(str(e), category='warning') return redirect(url('home')) self._graph(c.rhodecode_repo, collection, c.total_cs, c.size, p) c.branch_name = branch_name c.branch_filters = [('', _('All Branches'))] + \ [(k, k) for k in c.rhodecode_repo.branches.keys()] return render('changelog/changelog.html')
def get_member(member_search, set_html_action_fallback=False, search_email=False): """ Shortcut to return a member and raise not found automatically (as these are common opertations every time a member is fetched) """ # Concept of 'me' in API if isinstance(member_search, basestring) and member_search.lower()=='me': if not c.logged_in_persona: raise action_error(_("cannot refer to 'me' when not logged in"), code=400) member_search = c.logged_in_persona member = _get_member(member_search) if not member and search_email: member = _get_member_email(member_search) if not member: raise action_error(_("member %s not found" % member_search), code=404) if member.status != "active": raise action_error(_("member %s is inactive" % member.username) , code=404) if set_html_action_fallback: # AllanC - see _get_content for rational behind this c.html_action_fallback_url = url('member', id=member.username) return member
def add_home(self, repo_name, revision, f_path): repo = Repository.get_by_repo_name(repo_name) if repo.enable_locking and repo.locked[0]: h.flash( _('This repository has been locked by %s on %s') % (h.person_by_id(repo.locked[0]), h.format_date(h.time_to_datetime(repo.locked[1]))), 'warning') return redirect( h.url('files_home', repo_name=repo_name, revision='tip')) c.commit = self.__get_commit_or_redirect(revision, repo_name, redirect_after=False) if c.commit is None: c.commit = EmptyCommit(alias=c.rhodecode_repo.alias) c.default_message = (_('Added file via RhodeCode Enterprise')) c.f_path = f_path return render('files/files_add.html')
def join_group(group, member, delay_commit=False): return_value = True group = get_group(group) member = get_member(member) membership = get_membership(group, member) if not group: raise action_error(_('unable to find group'), code=404) if not member: raise action_error(_('unable to find member to add'), code=404) # AllanC - join permissions moved to controller if membership and membership.status == "invite": membership.status = "active" else: membership = GroupMembership() membership.group = group membership.member = member membership.role = group.default_role group.members_roles.append(membership) # If a join request if group.join_mode == "invite_and_request": membership.status = "request" return_value = "request" group.send_notification( messages.group_join_request(member=member, group=group)) # If user has actually become a member (open or reply to invite) then notify group if return_value == True: group.send_notification( messages.group_new_member(member=member, group=group)) if not delay_commit: Session.commit() #invalidate_member(group) #invalidate_member(member) return return_value
def import_status(self, taskid): "import status" result = AsyncResult(taskid) if result is None or taskid not in session['taskids']: flash(_('The task status requested has expired or does not exist')) redirect(url(controller='accounts', action='index')) if result.ready(): finished = True flash.pop_messages() if isinstance(result.result, Exception): if c.user.is_superadmin: flash_alert( _('Error occured in processing %s') % result.result) else: flash_alert(_('Backend error occured during processing.')) redirect(url(controller='accounts')) update_serial.delay() audit_log(c.user.username, 3, ACCOUNTIMPORT_MSG, request.host, request.remote_addr, now()) else: session['acimport-count'] += 1 if (session['acimport-count'] >= 10 and result.state in ['PENDING', 'RETRY', 'FAILURE']): result.revoke() try: os.unlink(session['acimport-file']) except OSError: pass del session['acimport-count'] session.save() flash_alert( _('The import could not be processed,' ' try again later')) redirect(url(controller='accounts')) finished = False c.finished = finished c.results = result.result c.success = result.successful() return render('/accounts/importstatus.html')
def add(self): """/accounts/new""" c.form = AddUserForm(request.POST, csrf_context=session) if c.user.is_domain_admin: account_types = (('3', 'User'), ) c.form.account_type.choices = account_types c.form.domains.query = Session.query(Domain).join(dom_owns, (oas, dom_owns.c.organization_id == oas.c.organization_id))\ .filter(oas.c.user_id == c.user.id) else: c.form.domains.query = Session.query(Domain) if request.POST and c.form.validate(): try: user = User(username=c.form.username.data, email=c.form.email.data) for attr in [ 'firstname', 'lastname', 'email', 'active', 'account_type', 'send_report', 'spam_checks', 'low_score', 'high_score', 'timezone' ]: setattr(user, attr, getattr(c.form, attr).data) user.local = True user.set_password(c.form.password1.data) if int(user.account_type) == 3: user.domains = c.form.domains.data Session.add(user) Session.commit() update_serial.delay() info = ADDACCOUNT_MSG % dict(u=user.username) audit_log(c.user.username, 3, info, request.host, request.remote_addr, now()) flash( _('The account: %(user)s was created successfully') % {'user': c.form.username.data}) redirect(url('account-detail', userid=user.id)) except IntegrityError: Session.rollback() flash_alert( _('Either the username or email address already exist')) return render('/accounts/new.html')
def verify_expiration(lic_dic): """ verify that license has not expired by now :param lic_dic: the dict with the license date :return: boolean - true if still valid """ if "expire" not in lic_dic: msg = "%s %r" % (_("no license expiration information in license "), lic_dic.info()) log.error(msg) return (False, msg) if "subscription" not in lic_dic: msg = "%s %r" % (_("no license subscription information in license"), lic_dic.info()) log.error(msg) return (False, msg) # we check only for the date string which has to be the first part of # the expiration date definition temp = (lic_dic.get('expire', '') or '').strip() if temp: expire = temp.split()[0].strip() if expire.lower() not in ('never'): return check_date('expire', expire) temp = (lic_dic.get('subscription', '') or '').strip() if temp: subscription = temp.split()[0].strip() return check_date('subscription', subscription) # old style license, we have to check the date entry for the subscription temp = (lic_dic.get('date', '') or '').strip() if temp: subscription = temp.split()[0].strip() return check_date('date', subscription) msg = _("invalid license (old license style)") return (False, msg)
def delete(self, name): """ Deletes a share from the backend. Keyword arguments: name -- the name of the share to be deleted Returns: A boolean value indicating if the Share was deleted sucessfuly """ deleted = False name = name.strip() try: if len(name) == 0: raise ShareError( _("You did not specify a Share to be removed.")) if not self.share_name_exists(name): raise ShareError(_("Can't delete a Share that doesn't exist!")) pos = self.__get_section_position(name) if pos['start'] == -1: raise ShareError( _("You did not specify a Share to be removed.")) before = self.__smbconf_content[0:pos['start']] after = self.__smbconf_content[pos['end']:] if self.__save_smbconf([before, after]): if self.__section_exists(name): self._set_error( _("Could not delete that Share.\ The Share is still in the Backend.\ No idea why..."), "critical") else: deleted = True except ShareError, error: self._set_error(error.message, error.type)
class ReleaseMsgForm(Form): "Release messages form" def validate_all(self): "validate all" errors = [] if (not self.release.data and not self.delete.data and not self.learn.data): errors.append(_('Select atleast one action to perform')) return errors def validate(self): "validate" if not Form.validate(self): return False errors = self.validate_all() if errors: self._errors = {'all': errors} return False return True def validate_altrecipients(self, field): "validate alt recipients" if self.usealt.data and not field.data and self.release.data: raise validators.ValidationError( _('Provide atleast one alternative recipient')) if self.usealt.data and field.data and self.release.data: emails = field.data.split(',') for email in emails: if not EMAIL_RE.match(email.strip()): raise validators.ValidationError( _('Invalid email address')) release = BooleanField(_('Release'), default=False) delete = BooleanField(_('Delete'), default=False) learn = BooleanField(_('Bayesian Learn'), default=False) usealt = BooleanField(_('Alt recipients'), default=False) learnas = SelectField('', choices=LEARN_OPTS) altrecipients = TextField('')
def export_accounts(self, domainid=None, orgid=None): "export domains" task = exportaccounts.apply_async(args=[domainid, c.user.id, orgid]) if 'taskids' not in session: session['taskids'] = [] session['taskids'].append(task.task_id) session['acexport-count'] = 1 session.save() msg = _('Accounts export is being processed') flash(msg) log.info(msg) redirect(url('accounts-export-status', taskid=task.task_id))
def __get_cs_or_redirect(self, rev, repo_name, redirect_after=True): """ Safe way to get changeset if error occur it redirects to tip with proper message :param rev: revision to fetch :param repo_name: repo name to redirect after """ try: return c.rhodecode_repo.get_changeset(rev) except EmptyRepositoryError, e: if not redirect_after: return None url_ = url('files_add_home', repo_name=c.repo_name, revision=0, f_path='') add_new = h.link_to(_('Click here to add new file'), url_) h.flash(h.literal(_('There are no files yet %s') % add_new), category='warning') redirect(h.url('summary_home', repo_name=repo_name))
def delete(self, userid): """/accounts/delete/id""" user = self._get_user(userid) if not user: abort(404) c.form = EditUserForm(request.POST, user, csrf_context=session) del c.form.domains if request.method == 'POST': if c.form.validate(): delete_user(user, c.user, request.host, request.remote_addr) flash(_('The account has been deleted')) redirect(url(controller='accounts', action='index')) else: flash_info( _('The account: %(a)s and all associated data' ' will be deleted, This action is not reversible.') % dict(a=user.username)) c.fields = FORM_FIELDS c.id = userid return self.render('/accounts/delete.html')
def systemstatus(): "process via mq" logger = systemstatus.get_logger() logger.info(_("Checking system status")) stats = dict(mem=None, cpu=None, load=None, net=[], mta=None, scanners=None, time=None, uptime=None, av=None, partitions=[]) def _obj2dict(obj): "convert object attribs to dict" val = {} for key in obj._fields: val[key] = getattr(obj, key) return val pipe = subprocess.Popen(["uptime"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) upt = pipe.communicate()[0].split() pipe.wait(timeout=2) pipe = subprocess.Popen(["date"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) stats['time'] = pipe.communicate()[0] pipe.wait(timeout=2) stats['uptime'] = "%s %s" % (upt[2], upt[3].rstrip(',')) stats['mem'] = _obj2dict(psutil.phymem_usage()) stats['cpu'] = psutil.cpu_percent() stats['load'] = os.getloadavg() net = psutil.network_io_counters(True) infs = {} for inf in net: infs[inf] = _obj2dict(net[inf]) stats['net'] = infs partitions = [] for part in psutil.disk_partitions(all=False): usage = psutil.disk_usage(part.mountpoint) dpart = _obj2dict(part) dpart.update(_obj2dict(usage)) partitions.append(dpart) stats['partitions'] = partitions stats['mta'] = get_processes('exim') stats['scanners'] = get_processes('MailScanner') stats['av'] = get_processes('clamd') return stats
def __load_data(self, repo_name=None): """ Load defaults settings for edit, and update :param repo_name: """ self.__load_defaults() c.repo_info = db_repo = Repository.get_by_repo_name(repo_name) repo = db_repo.scm_instance if c.repo_info is None: h.not_mapped_error(repo_name) return redirect(url('repos')) ##override defaults for exact repo info here git/hg etc choices, c.landing_revs = ScmModel().get_repo_landing_revs(c.repo_info) c.landing_revs_choices = choices c.default_user_id = User.get_by_username('default').user_id c.in_public_journal = UserFollowing.query()\ .filter(UserFollowing.user_id == c.default_user_id)\ .filter(UserFollowing.follows_repository == c.repo_info).scalar() if c.repo_info.stats: # this is on what revision we ended up so we add +1 for count last_rev = c.repo_info.stats.stat_on_revision + 1 else: last_rev = 0 c.stats_revision = last_rev c.repo_last_rev = repo.count() if repo.revisions else 0 if last_rev == 0 or c.repo_last_rev == 0: c.stats_percentage = 0 else: c.stats_percentage = '%.2f' % ((float( (last_rev)) / c.repo_last_rev) * 100) c.repo_fields = RepositoryField.query()\ .filter(RepositoryField.repository == db_repo).all() defaults = RepoModel()._get_defaults(repo_name) c.repos_list = [('', _('--REMOVE FORK--'))] c.repos_list += [ (x.repo_id, x.repo_name) for x in Repository.query().order_by(Repository.repo_name).all() if x.repo_id != c.repo_info.repo_id ] defaults['id_fork_of'] = db_repo.fork.repo_id if db_repo.fork else '' return defaults
class AddAuthForm(Form): """Add auth server""" address = TextField(_('Server address'), [validators.Required(), check_server_addr]) protocol = SelectField(_('Protocol'), choices=list(AUTH_PROTOCOLS)) port = TextField(_('Port'), [validators.Regexp(NUMORSPACE_RE, message=_('must be numeric'))]) enabled = BooleanField(_('Enabled'), default=True) split_address = BooleanField(_('Split address'), default=False) user_map_template = TextField(_('Username map template'))
def __before__(self): super(BaseRepoController, self).__before__() if c.repo_name: # extracted from routes db_repo = Repository.get_by_repo_name(c.repo_name) if not db_repo: return log.debug( 'Found repository in database %s with state `%s`', safe_unicode(db_repo), safe_unicode(db_repo.repo_state)) route = getattr(request.environ.get('routes.route'), 'name', '') # allow to delete repos that are somehow damages in filesystem if route in ['delete_repo']: return if db_repo.repo_state in [Repository.STATE_PENDING]: if route in ['repo_creating_home']: return check_url = url('repo_creating_home', repo_name=c.repo_name) return redirect(check_url) self.rhodecode_db_repo = db_repo missing_requirements = False try: self.rhodecode_repo = self.rhodecode_db_repo.scm_instance() except RepositoryRequirementError as e: missing_requirements = True self._handle_missing_requirements(e) if self.rhodecode_repo is None and not missing_requirements: log.error('%s this repository is present in database but it ' 'cannot be created as an scm instance', c.repo_name) h.flash(_( "The repository at %(repo_name)s cannot be located.") % {'repo_name': c.repo_name}, category='error', ignore_duplicate=True) redirect(url('home')) # update last change according to VCS data if not missing_requirements: commit = db_repo.get_commit( pre_load=["author", "date", "message", "parents"]) db_repo.update_commit_cache(commit) # Prepare context c.rhodecode_db_repo = db_repo c.rhodecode_repo = self.rhodecode_repo c.repository_requirements_missing = missing_requirements self._update_global_counters(self.scm_model, db_repo)