def add_user_to_group(group, user): ugm = UsersGroupMember() ugm.users_group = group ugm.user = user Session.add(ugm) Session.commit() return ugm
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) self.__load_defaults() repo_model = RepoModel() changed_name = repo_name _form = RepoForm(edit=True, old_data={'repo_name': repo_name}, repo_groups=c.repo_groups_choices)() try: form_result = _form.to_python(dict(request.POST)) repo = repo_model.update(repo_name, form_result) invalidate_cache('get_repo_cached_%s' % repo_name) h.flash(_('Repository %s updated successfully' % repo_name), category='success') changed_name = repo.repo_name action_logger(self.rhodecode_user, 'admin_updated_repo', changed_name, '', 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")
def test_propagated_permission_from_users_group_lower_weight(self): # make group self.ug1 = UsersGroupModel().create('G1') # add user to group UsersGroupModel().add_user_to_group(self.ug1, self.u1) # set permission to lower new_perm_h = 'repository.write' RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1, perm=new_perm_h) Session.commit() u1_auth = AuthUser(user_id=self.u1.user_id) self.assertEqual(u1_auth.permissions['repositories'][HG_REPO], new_perm_h) # grant perm for group this should NOT override permission from user # since it's lower than granted new_perm_l = 'repository.read' RepoModel().grant_users_group_permission(repo=HG_REPO, group_name=self.ug1, perm=new_perm_l) # check perms u1_auth = AuthUser(user_id=self.u1.user_id) perms = { 'repositories_groups': {}, 'global': set([u'hg.create.repository', u'repository.read', u'hg.register.manual_activate']), 'repositories': {u'vcs_test_hg': u'repository.write'} } self.assertEqual(u1_auth.permissions['repositories'][HG_REPO], new_perm_h) self.assertEqual(u1_auth.permissions['repositories_groups'], perms['repositories_groups'])
def revoke_users_group_permission(self, apiuser, repo_name, group_name): """ Revoke permission for users group on given repository :param repo_name: :param group_name: """ try: repo = Repository.get_by_repo_name(repo_name) if repo is None: raise JSONRPCError('unknown repository %s' % repo) user_group = UsersGroup.get_by_group_name(group_name) if user_group is None: raise JSONRPCError('unknown users group %s' % user_group) RepoModel().revoke_users_group_permission(repo=repo_name, group_name=group_name) Session.commit() return dict( msg='Revoked perm for group: %s in repo: %s' % ( group_name, repo_name ) ) except Exception: log.error(traceback.format_exc()) raise JSONRPCError( 'failed to edit permission %(repo)s for %(usersgr)s' % dict( usersgr=group_name, repo=repo_name ) )
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() c.user = user_model.get(id) _form = UserForm(edit=True, old_data={'user_id': id, 'email': c.user.email})() form_result = {} try: form_result = _form.to_python(dict(request.POST)) user_model.update(id, form_result) h.flash(_('User updated successfully'), category='success') Session.commit() except formencode.Invalid, errors: e = errors.error_dict or {} perm = Permission.get_by_key('hg.create.repository') e.update({'create_repo_perm': user_model.has_perm(id, perm)}) return htmlfill.render( render('admin/users/user_edit.html'), defaults=errors.value, errors=e, prefix_error=False, encoding="UTF-8")
def add_user_to_users_group(self, apiuser, group_name, username): """" Add a user to a users group :param apiuser: :param group_name: :param username: """ try: users_group = UsersGroup.get_by_group_name(group_name) if not users_group: raise JSONRPCError('unknown users group %s' % group_name) user = User.get_by_username(username) if user is None: raise JSONRPCError('unknown user %s' % username) ugm = UsersGroupModel().add_user_to_group(users_group, user) success = True if ugm != True else False msg = 'added member %s to users group %s' % (username, group_name) msg = msg if success else 'User is already in that group' Session.commit() return dict( id=ugm.users_group_member_id if ugm != True else None, success=success, msg=msg ) except Exception: log.error(traceback.format_exc()) raise JSONRPCError('failed to add users group member')
def grant_user_permission(self, apiuser, repo_name, username, perm): """ Grant permission for user on given repository, or update existing one if found :param repo_name: :param username: :param perm: """ try: repo = Repository.get_by_repo_name(repo_name) if repo is None: raise JSONRPCError('unknown repository %s' % repo) user = User.get_by_username(username) if user is None: raise JSONRPCError('unknown user %s' % username) RepoModel().grant_user_permission(repo=repo, user=user, perm=perm) Session.commit() return dict( msg='Granted perm: %s for user: %s in repo: %s' % ( perm, username, repo_name ) ) except Exception: log.error(traceback.format_exc()) raise JSONRPCError( 'failed to edit permission %(repo)s for %(user)s' % dict( user=username, repo=repo_name ) )
def create(self): """POST /repos_groups: Create a new item""" # url('repos_groups') self.__load_defaults() repos_group_form = ReposGroupForm(available_groups = c.repo_groups_choices)() try: form_result = repos_group_form.to_python(dict(request.POST)) ReposGroupModel().create( group_name=form_result['group_name'], group_description=form_result['group_description'], parent=form_result['group_parent_id'] ) Session.commit() h.flash(_('created repos group %s') \ % form_result['group_name'], category='success') #TODO: in futureaction_logger(, '', '', '', self.sa) except formencode.Invalid, errors: return htmlfill.render( render('admin/repos_groups/repos_groups_add.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8")
def update(self, id): """PUT /repos_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('repos_group', id=ID), # method='put') # url('repos_group', id=ID) self.__load_defaults() c.repos_group = RepoGroup.get(id) repos_group_form = ReposGroupForm( edit=True, old_data=c.repos_group.get_dict(), available_groups=c.repo_groups_choices )() try: form_result = repos_group_form.to_python(dict(request.POST)) ReposGroupModel().update(id, form_result) Session.commit() h.flash(_('updated repos group %s') \ % form_result['group_name'], category='success') #TODO: in futureaction_logger(, '', '', '', self.sa) except formencode.Invalid, errors: return htmlfill.render( render('admin/repos_groups/repos_groups_edit.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8")
def test_delete(self): self.log_user() cur_user = self._get_logged_user() u1 = UserModel().create_or_update(username='******', password='******', email='*****@*****.**', name='u1', lastname='u1') u2 = UserModel().create_or_update(username='******', password='******', email='*****@*****.**', name='u2', lastname='u2') # make notifications notification = NotificationModel().create(created_by=cur_user, subject=u'test', body=u'hi there', recipients=[cur_user, u1, u2]) Session.commit() u1 = User.get(u1.user_id) u2 = User.get(u2.user_id) # check DB get_notif = lambda un:[x.notification for x in un] self.assertEqual(get_notif(cur_user.notifications), [notification]) self.assertEqual(get_notif(u1.notifications), [notification]) self.assertEqual(get_notif(u2.notifications), [notification]) cur_usr_id = cur_user.user_id response = self.app.delete(url('notification', notification_id= notification.notification_id)) cur_user = User.get(cur_usr_id) self.assertEqual(cur_user.notifications, [])
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 my_account_update(self): """PUT /_admin/my_account_update: 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('admin_settings_my_account_update'), # method='put') # url('admin_settings_my_account_update', id=ID) user_model = UserModel() uid = self.rhodecode_user.user_id _form = UserForm(edit=True, old_data={'user_id': uid, 'email': self.rhodecode_user.email})() form_result = {} try: form_result = _form.to_python(dict(request.POST)) user_model.update_my_account(uid, form_result) h.flash(_('Your account was updated successfully'), category='success') Session.commit() except formencode.Invalid, errors: c.user = User.get(self.rhodecode_user.user_id) all_repos = self.sa.query(Repository)\ .filter(Repository.user_id == c.user.user_id)\ .order_by(func.lower(Repository.repo_name))\ .all() c.user_repos = ScmModel().get_repos(all_repos) return htmlfill.render( render('admin/users/user_edit_my_account.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8")
def update(self, repo_name): repo_model = RepoModel() changed_name = repo_name self.__load_defaults() _form = RepoSettingsForm(edit=True, old_data={'repo_name': repo_name}, repo_groups=c.repo_groups_choices)() try: form_result = _form.to_python(dict(request.POST)) repo_model.update(repo_name, form_result) invalidate_cache('get_repo_cached_%s' % repo_name) h.flash(_('Repository %s updated successfully' % repo_name), category='success') changed_name = form_result['repo_name_full'] action_logger(self.rhodecode_user, 'user_updated_repo', changed_name, '', self.sa) Session.commit() except formencode.Invalid, errors: c.repo_info = repo_model.get_by_repo_name(repo_name) c.users_array = repo_model.get_users_js() errors.value.update({'user': c.repo_info.user.username}) return htmlfill.render( render('settings/repo_settings.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8")
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.flash(_('%s repository is not mapped to db perhaps' ' it was moved or renamed from the filesystem' ' please run the application again' ' in order to rescan repositories') % repo_name, category='error') return redirect(url('home')) try: action_logger(self.rhodecode_user, 'user_deleted_repo', repo_name, '', 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('home'))
def update_lastlogin(self): """Update user lastlogin""" self.last_login = datetime.datetime.now() Session.add(self) Session.commit() log.debug("updated user %s lastlogin" % self.username)
def delete(self, id): """DELETE /repos_groups/id: 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', id=ID), # method='delete') # url('repos_group', id=ID) gr = RepoGroup.get(id) repos = gr.repositories.all() if repos: h.flash(_('This group contains %s repositores and cannot be ' 'deleted' % len(repos)), category='error') return redirect(url('repos_groups')) try: ReposGroupModel().delete(id) Session.commit() h.flash(_('removed repos group %s' % gr.group_name), category='success') #TODO: in future action_logger(, '', '', '', self.sa) except IntegrityError, e: if e.message.find('groups_group_parent_id_fkey') != -1: log.error(traceback.format_exc()) h.flash(_('Cannot delete this group it still contains ' 'subgroups'), category='warning') else: log.error(traceback.format_exc()) h.flash(_('error occurred during deletion of repos ' 'group %s' % gr.group_name), category='error')
def update_user(self, apiuser, userid, username, password, email, firstname, lastname, active, admin, ldap_dn): """ Updates given user :param apiuser: :param username: :param password: :param email: :param name: :param lastname: :param active: :param admin: :param ldap_dn: """ if not UserModel().get_user(userid): raise JSONRPCError("user %s does not exist" % username) try: usr = UserModel().create_or_update( username, password, email, firstname, lastname, active, admin, ldap_dn ) Session.commit() return dict( id=usr.user_id, msg='updated user %s' % username ) except Exception: log.error(traceback.format_exc()) raise JSONRPCError('failed to update user %s' % username)
def register(self): c.auto_active = False for perm in User.get_by_username('default').user_perms: if perm.permission.permission_name == 'hg.register.auto_activate': c.auto_active = True break if request.POST: register_form = RegisterForm()() try: form_result = register_form.to_python(dict(request.POST)) form_result['active'] = c.auto_active UserModel().create_registration(form_result) h.flash(_('You have successfully registered into rhodecode'), category='success') Session.commit() return redirect(url('login_home')) except formencode.Invalid, errors: return htmlfill.render( render('/register.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8")
def remove_user_from_users_group(self, apiuser, group_name, username): """ Remove user from a group :param apiuser :param group_name :param username """ try: users_group = UsersGroup.get_by_group_name(group_name) if not users_group: raise JSONRPCError('unknown users group %s' % group_name) user = User.get_by_username(username) if user is None: raise JSONRPCError('unknown user %s' % username) success = UsersGroupModel().remove_user_from_group(users_group, user) msg = 'removed member %s from users group %s' % (username, group_name) msg = msg if success else "User wasn't in group" Session.commit() return dict(success=success, msg=msg) except Exception: log.error(traceback.format_exc()) raise JSONRPCError('failed to remove user from group')
def test_notification_counter(self): self._clean_notifications() self.assertEqual([], Notification.query().all()) self.assertEqual([], UserNotification.query().all()) NotificationModel().create(created_by=self.u1, subject=u'title', body=u'hi there_delete', recipients=[self.u3, self.u1]) Session.commit() self.assertEqual(NotificationModel() .get_unread_cnt_for_user(self.u1), 1) self.assertEqual(NotificationModel() .get_unread_cnt_for_user(self.u2), 0) self.assertEqual(NotificationModel() .get_unread_cnt_for_user(self.u3), 1) notification = NotificationModel().create(created_by=self.u1, subject=u'title', body=u'hi there3', recipients=[self.u3, self.u1, self.u2]) Session.commit() self.assertEqual(NotificationModel() .get_unread_cnt_for_user(self.u1), 2) self.assertEqual(NotificationModel() .get_unread_cnt_for_user(self.u2), 1) self.assertEqual(NotificationModel() .get_unread_cnt_for_user(self.u3), 2)
def toggle_following(self): cur_token = request.POST.get('auth_token') token = h.get_token() if cur_token == token: user_id = request.POST.get('follows_user_id') if user_id: try: self.scm_model.toggle_following_user(user_id, self.rhodecode_user.user_id) Session.commit() return 'ok' except: raise HTTPBadRequest() repo_id = request.POST.get('follows_repo_id') if repo_id: try: self.scm_model.toggle_following_repo(repo_id, self.rhodecode_user.user_id) Session.commit() return 'ok' except: raise HTTPBadRequest() log.debug('token mismatch %s vs %s' % (cur_token, token)) raise HTTPBadRequest()
def tearDown(self): perm = Permission.query().all() for p in perm: UserModel().revoke_perm(self.u1, p) UserModel().delete(self.u1) Session.commit()
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 update(self, id): """PUT /permissions/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('permission', id=ID), # method='put') # url('permission', id=ID) permission_model = PermissionModel() _form = DefaultPermissionsForm([x[0] for x in self.perms_choices], [x[0] for x in self.register_choices], [x[0] for x in self.create_choices])() try: form_result = _form.to_python(dict(request.POST)) form_result.update({'perm_user_name': id}) permission_model.update(form_result) Session.commit() h.flash(_('Default permissions updated successfully'), category='success') except formencode.Invalid, errors: c.perms_choices = self.perms_choices c.register_choices = self.register_choices c.create_choices = self.create_choices defaults = errors.value return htmlfill.render( render('admin/permissions/permissions.html'), defaults=defaults, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8")
def delete_comment(self, repo_name, comment_id): co = ChangesetComment.get(comment_id) owner = lambda: co.author.user_id == c.rhodecode_user.user_id if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner: ChangesetCommentsModel().delete(comment=co) Session.commit() return True else: raise HTTPForbidden()
def create_or_update_hook(cls, key, val): new_ui = cls.get_by_key(key).scalar() or cls() new_ui.ui_section = "hooks" new_ui.ui_active = True new_ui.ui_key = key new_ui.ui_value = val Session.add(new_ui) Session.commit()
def revoke_perm(cls, users_group_id, perm): if not isinstance(perm, Permission): raise Exception("perm needs to be an instance of Permission class") try: cls.query().filter(cls.users_group_id == users_group_id).filter(cls.permission == perm).delete() Session.commit() except: Session.rollback()
def set_valid(cls, key): """ Mark this cache key as active and currently cached :param key: """ inv_obj = Session.query(CacheInvalidation).filter(CacheInvalidation.cache_key == key).scalar() inv_obj.cache_active = True Session.add(inv_obj) Session.commit()
def set_valid(cls, key): """ Mark this cache key as active and currently cached :param key: """ inv_obj = cls.get_by_key(key) inv_obj.cache_active = True Session.add(inv_obj) Session.commit()
def test_revoke_perm(self): perm = Permission.query().all()[0] UserModel().grant_perm(self.u1, perm) Session.commit() self.assertEqual(UserModel().has_perm(self.u1, perm), True) #revoke UserModel().revoke_perm(self.u1, perm) Session.commit() self.assertEqual(UserModel().has_perm(self.u1, perm), False)
def create_user(self, apiuser, username, email, password, firstname=None, lastname=None, active=True, admin=False, ldap_dn=None): """ Create new user :param apiuser: :param username: :param password: :param email: :param name: :param lastname: :param active: :param admin: :param ldap_dn: """ if User.get_by_username(username): raise JSONRPCError("user %s already exist" % username) if User.get_by_email(email, case_insensitive=True): raise JSONRPCError("email %s already exist" % email) if ldap_dn: # generate temporary password if ldap_dn password = PasswordGenerator().gen_password(length=8) try: usr = UserModel().create_or_update( username, password, email, firstname, lastname, active, admin, ldap_dn ) Session.commit() return dict( id=usr.user_id, msg='created new user %s' % username ) except Exception: log.error(traceback.format_exc()) raise JSONRPCError('failed to create user %s' % username)
def grant_users_group_permission(self, apiuser, repo_name, group_name, perm): """ Grant permission for users group on given repository, or update existing one if found :param repo_name: :param group_name: :param perm: """ try: repo = Repository.get_by_repo_name(repo_name) if repo is None: raise JSONRPCError('unknown repository %s' % repo) user_group = UsersGroup.get_by_group_name(group_name) if user_group is None: raise JSONRPCError('unknown users group %s' % user_group) RepoModel().grant_users_group_permission(repo=repo_name, group_name=group_name, perm=perm) Session.commit() return dict( msg='Granted perm: %s for group: %s in repo: %s' % ( perm, group_name, repo_name ) ) except Exception: log.error(traceback.format_exc()) raise JSONRPCError( 'failed to edit permission %(repo)s for %(usersgr)s' % dict( usersgr=group_name, repo=repo_name ) )
def update(cls, users_group_id, form_data): try: users_group = cls.get(users_group_id, cache=False) for k, v in form_data.items(): if k == 'users_group_members': users_group.members = [] Session.flush() members_list = [] if v: v = [v] if isinstance(v, basestring) else v for u_id in set(v): member = UserGroupMember(users_group_id, u_id) members_list.append(member) setattr(users_group, 'members', members_list) setattr(users_group, k, v) Session.add(users_group) Session.commit() except: log.error(traceback.format_exc()) Session.rollback() raise
def my_account_update(self): """PUT /_admin/my_account_update: 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('admin_settings_my_account_update'), # method='put') # url('admin_settings_my_account_update', id=ID) user_model = UserModel() uid = self.rhodecode_user.user_id _form = UserForm(edit=True, old_data={ 'user_id': uid, 'email': self.rhodecode_user.email })() form_result = {} try: form_result = _form.to_python(dict(request.POST)) user_model.update_my_account(uid, form_result) h.flash(_('Your account was updated successfully'), category='success') Session.commit() except formencode.Invalid, errors: c.user = User.get(self.rhodecode_user.user_id) all_repos = self.sa.query(Repository)\ .filter(Repository.user_id == c.user.user_id)\ .order_by(func.lower(Repository.repo_name))\ .all() c.user_repos = ScmModel().get_repos(all_repos) return htmlfill.render( render('admin/users/user_edit_my_account.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8")
def create(self): """POST /repos_groups: Create a new item""" # url('repos_groups') self.__load_defaults() repos_group_form = ReposGroupForm( available_groups=c.repo_groups_choices)() try: form_result = repos_group_form.to_python(dict(request.POST)) ReposGroupModel().create( group_name=form_result['group_name'], group_description=form_result['group_description'], parent=form_result['group_parent_id']) Session.commit() h.flash(_('created repos group %s') \ % form_result['group_name'], category='success') #TODO: in futureaction_logger(, '', '', '', self.sa) except formencode.Invalid, errors: return htmlfill.render( render('admin/repos_groups/repos_groups_add.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8")
def test_create_notification(self): self.assertEqual([], Notification.query().all()) self.assertEqual([], UserNotification.query().all()) usrs = [self.u1, self.u2] notification = NotificationModel().create(created_by=self.u1, subject=u'subj', body=u'hi there', recipients=usrs) Session.commit() u1 = User.get(self.u1) u2 = User.get(self.u2) u3 = User.get(self.u3) notifications = Notification.query().all() self.assertEqual(len(notifications), 1) unotification = UserNotification.query()\ .filter(UserNotification.notification == notification).all() self.assertEqual(notifications[0].recipients, [u1, u2]) self.assertEqual(notification.notification_id, notifications[0].notification_id) self.assertEqual(len(unotification), len(usrs)) self.assertEqual([x.user.user_id for x in unotification], usrs)
def test_default_perms_set(self): u1_auth = AuthUser(user_id=self.u1.user_id) perms = { 'repositories_groups': {}, 'global': set([ u'hg.create.repository', u'repository.read', u'hg.register.manual_activate' ]), 'repositories': { u'vcs_test_hg': u'repository.read' } } self.assertEqual(u1_auth.permissions['repositories'][HG_REPO], perms['repositories'][HG_REPO]) new_perm = 'repository.write' RepoModel().grant_user_permission(repo=HG_REPO, user=self.u1, perm=new_perm) Session.commit() u1_auth = AuthUser(user_id=self.u1.user_id) self.assertEqual(u1_auth.permissions['repositories'][HG_REPO], new_perm)
def show(self, notification_id, format='html'): """GET /_admin/notifications/id: Show a specific item""" # url('notification', notification_id=ID) c.user = self.rhodecode_user no = Notification.get(notification_id) owner = lambda: (no.notifications_to_users.user.user_id == c.user. user_id) if no and (h.HasPermissionAny('hg.admin', 'repository.admin')() or owner): unotification = NotificationModel()\ .get_user_notification(c.user.user_id, no) # if this association to user is not valid, we don't want to show # this message if unotification: if unotification.read is False: unotification.mark_as_read() Session.commit() c.notification = no return render('admin/notifications/show_notification.html') return redirect(url('notifications'))
def test_repo_group_user_as_user_group_member(self): # create Group1 self.g1 = _make_group('group1', skip_if_exists=True) Session.commit() a1_auth = AuthUser(user_id=self.anon.user_id) self.assertEqual(a1_auth.permissions['repositories_groups'], {u'group1': u'group.read'}) # set default permission to none ReposGroupModel().grant_user_permission(repos_group=self.g1, user=self.anon, perm='group.none') # make group self.ug1 = UsersGroupModel().create('G1') # add user to group UsersGroupModel().add_user_to_group(self.ug1, self.u1) Session.commit() # check if user is in the group membrs = [ x.user_id for x in UsersGroupModel().get(self.ug1.users_group_id).members ] self.assertEqual(membrs, [self.u1.user_id]) # add some user to that group # check his permissions a1_auth = AuthUser(user_id=self.anon.user_id) self.assertEqual(a1_auth.permissions['repositories_groups'], {u'group1': u'group.none'}) u1_auth = AuthUser(user_id=self.u1.user_id) self.assertEqual(u1_auth.permissions['repositories_groups'], {u'group1': u'group.none'}) # grant ug1 read permissions for ReposGroupModel().grant_users_group_permission(repos_group=self.g1, group_name=self.ug1, perm='group.read') Session.commit() # check if the obj = Session.query(UsersGroupRepoGroupToPerm)\ .filter(UsersGroupRepoGroupToPerm.group == self.g1)\ .filter(UsersGroupRepoGroupToPerm.users_group == self.ug1)\ .scalar() self.assertEqual(obj.permission.permission_name, 'group.read') a1_auth = AuthUser(user_id=self.anon.user_id) self.assertEqual(a1_auth.permissions['repositories_groups'], {u'group1': u'group.none'}) u1_auth = AuthUser(user_id=self.u1.user_id) self.assertEqual(u1_auth.permissions['repositories_groups'], {u'group1': u'group.read'})
def test_create_and_remove(self): usr = UserModel().create_or_update(username=u'test_user', password=u'qweqwe', email=u'*****@*****.**', name=u'u1', lastname=u'u1') Session.commit() self.assertEqual(User.get_by_username(u'test_user'), usr) # make users group users_group = UsersGroupModel().create('some_example_group') Session.commit() UsersGroupModel().add_user_to_group(users_group, usr) Session.commit() self.assertEqual(UsersGroup.get(users_group.users_group_id), users_group) self.assertEqual(UsersGroupMember.query().count(), 1) UserModel().delete(usr.user_id) Session.commit() self.assertEqual(UsersGroupMember.query().all(), [])
def test_move_to_root(self): g1 = _make_group('t11') Session.commit() g2 = _make_group('t22', parent_id=g1.group_id) Session.commit() self.assertEqual(g2.full_path, 't11/t22') self.assertTrue(self.__check_path('t11', 't22')) g2 = self.__update_group(g2.group_id, 'g22', parent_id=None) Session.commit() self.assertEqual(g2.group_name, 'g22') # we moved out group from t1 to '' so it's full path should be 'g2' self.assertEqual(g2.full_path, 'g22') self.assertFalse(self.__check_path('t11', 't22')) self.assertTrue(self.__check_path('g22'))
def test_repo_in_group_permissions(self): self.g1 = _make_group('group1', skip_if_exists=True) self.g2 = _make_group('group2', skip_if_exists=True) Session.commit() # both perms should be read ! u1_auth = AuthUser(user_id=self.u1.user_id) self.assertEqual(u1_auth.permissions['repositories_groups'], { u'group1': u'group.read', u'group2': u'group.read' }) a1_auth = AuthUser(user_id=self.anon.user_id) self.assertEqual(a1_auth.permissions['repositories_groups'], { u'group1': u'group.read', u'group2': u'group.read' }) #Change perms to none for both groups ReposGroupModel().grant_user_permission(repos_group=self.g1, user=self.anon, perm='group.none') ReposGroupModel().grant_user_permission(repos_group=self.g2, user=self.anon, perm='group.none') u1_auth = AuthUser(user_id=self.u1.user_id) self.assertEqual(u1_auth.permissions['repositories_groups'], { u'group1': u'group.none', u'group2': u'group.none' }) a1_auth = AuthUser(user_id=self.anon.user_id) self.assertEqual(a1_auth.permissions['repositories_groups'], { u'group1': u'group.none', u'group2': u'group.none' }) # add repo to group form_data = { 'repo_name': HG_REPO, 'repo_name_full': RepoGroup.url_sep().join([self.g1.group_name, HG_REPO]), 'repo_type': 'hg', 'clone_uri': '', 'repo_group': self.g1.group_id, 'description': 'desc', 'private': False } self.test_repo = RepoModel().create(form_data, cur_user=self.u1) Session.commit() u1_auth = AuthUser(user_id=self.u1.user_id) self.assertEqual(u1_auth.permissions['repositories_groups'], { u'group1': u'group.none', u'group2': u'group.none' }) a1_auth = AuthUser(user_id=self.anon.user_id) self.assertEqual(a1_auth.permissions['repositories_groups'], { u'group1': u'group.none', u'group2': u'group.none' }) #grant permission for u2 ! ReposGroupModel().grant_user_permission(repos_group=self.g1, user=self.u2, perm='group.read') ReposGroupModel().grant_user_permission(repos_group=self.g2, user=self.u2, perm='group.read') Session.commit() self.assertNotEqual(self.u1, self.u2) #u1 and anon should have not change perms while u2 should ! u1_auth = AuthUser(user_id=self.u1.user_id) self.assertEqual(u1_auth.permissions['repositories_groups'], { u'group1': u'group.none', u'group2': u'group.none' }) u2_auth = AuthUser(user_id=self.u2.user_id) self.assertEqual(u2_auth.permissions['repositories_groups'], { u'group1': u'group.read', u'group2': u'group.read' }) a1_auth = AuthUser(user_id=self.anon.user_id) self.assertEqual(a1_auth.permissions['repositories_groups'], { u'group1': u'group.none', u'group2': u'group.none' })
def tearDown(self): for n in Notification.query().all(): inst = Notification.get(n.notification_id) Session.delete(inst) Session.commit()
def test_add_perm(self): perm = Permission.query().all()[0] UserModel().grant_perm(self.u1, perm) Session.commit() self.assertEqual(UserModel().has_perm(self.u1, perm), True)
class DbManage(object): def __init__(self, log_sql, dbconf, root, tests=False, cli_args={}): self.dbname = dbconf.split('/')[-1] self.tests = tests self.root = root self.dburi = dbconf self.log_sql = log_sql self.db_exists = False self.cli_args = cli_args self.init_db() force_ask = self.cli_args.get('force_ask') if force_ask is not None: global ask_ok ask_ok = lambda *args, **kwargs: force_ask def init_db(self): engine = create_engine(self.dburi, echo=self.log_sql) init_model(engine) self.sa = Session() def create_tables(self, override=False): """ Create a auth database """ log.info("Any existing database is going to be destroyed") if self.tests: destroy = True else: destroy = ask_ok('Are you sure to destroy old database ? [y/n]') if not destroy: sys.exit('Nothing tables created') if destroy: Base.metadata.drop_all() checkfirst = not override Base.metadata.create_all(checkfirst=checkfirst) log.info('Created tables for %s' % self.dbname) def set_db_version(self): ver = DbMigrateVersion() ver.version = __dbversion__ ver.repository_id = 'rhodecode_db_migrations' ver.repository_path = 'versions' self.sa.add(ver) log.info('db version set to: %s' % __dbversion__) def upgrade(self): """ Upgrades given database schema to given revision following all needed steps, to perform the upgrade """ from rhodecode.lib.dbmigrate.migrate.versioning import api from rhodecode.lib.dbmigrate.migrate.exceptions import \ DatabaseNotControlledError if 'sqlite' in self.dburi: print('********************** WARNING **********************\n' 'Make sure your version of sqlite is at least 3.7.X. \n' 'Earlier versions are known to fail on some migrations\n' '*****************************************************\n') upgrade = ask_ok('You are about to perform database upgrade, make ' 'sure You backed up your database before. ' 'Continue ? [y/n]') if not upgrade: sys.exit('No upgrade performed') repository_path = jn(dn(dn(dn(os.path.realpath(__file__)))), 'rhodecode/lib/dbmigrate') db_uri = self.dburi try: curr_version = api.db_version(db_uri, repository_path) msg = ('Found current database under version' ' control with version %s' % curr_version) except (RuntimeError, DatabaseNotControlledError): curr_version = 1 msg = ('Current database is not under version control. Setting' ' as version %s' % curr_version) api.version_control(db_uri, repository_path, curr_version) notify(msg) if curr_version == __dbversion__: sys.exit('This database is already at the newest version') # clear cache keys log.info("Clearing cache keys now...") CacheInvalidation.clear_cache() upgrade_steps = range(curr_version + 1, __dbversion__ + 1) notify('attempting to do database upgrade from ' 'version %s to version %s' % (curr_version, __dbversion__)) # CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE _step = None for step in upgrade_steps: notify('performing upgrade step %s' % step) time.sleep(2) api.upgrade(db_uri, repository_path, step) notify('schema upgrade for step %s completed' % (step, )) fixture = 'step_%s' % step notify('performing fixture step %s' % fixture) getattr(UpgradeSteps(self), fixture)() self.sa.commit() notify('fixture %s completed' % (fixture, )) _step = step notify('upgrade to version %s successful' % _step) def fix_repo_paths(self): """ Fixes a old rhodecode version path into new one without a '*' """ paths = self.sa.query(RhodeCodeUi)\ .filter(RhodeCodeUi.ui_key == '/')\ .scalar() paths.ui_value = paths.ui_value.replace('*', '') try: self.sa.add(paths) self.sa.commit() except Exception: self.sa.rollback() raise def fix_default_user(self): """ Fixes a old default user with some 'nicer' default values, used mostly for anonymous access """ def_user = self.sa.query(User)\ .filter(User.username == 'default')\ .one() def_user.name = 'Anonymous' def_user.lastname = 'User' def_user.email = '*****@*****.**' try: self.sa.add(def_user) self.sa.commit() except Exception: self.sa.rollback() raise def fix_settings(self): """ Fixes rhodecode settings adds ga_code key for google analytics """ hgsettings3 = RhodeCodeSetting('ga_code', '') try: self.sa.add(hgsettings3) self.sa.commit() except Exception: self.sa.rollback() raise def admin_prompt(self, second=False): if not self.tests: import getpass # defaults defaults = self.cli_args username = defaults.get('username') password = defaults.get('password') email = defaults.get('email') def get_password(): password = getpass.getpass('Specify admin password ' '(min 6 chars):') confirm = getpass.getpass('Confirm password:'******'passwords mismatch') return False if len(password) < 6: log.error('password is to short use at least 6 characters') return False return password if username is None: username = raw_input('Specify admin username:'******'Specify admin email:') self.create_user(username, password, email, True) else: log.info('creating admin and regular test users') from rhodecode.tests import TEST_USER_ADMIN_LOGIN, \ TEST_USER_ADMIN_PASS, TEST_USER_ADMIN_EMAIL, \ TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, \ TEST_USER_REGULAR_EMAIL, TEST_USER_REGULAR2_LOGIN, \ TEST_USER_REGULAR2_PASS, TEST_USER_REGULAR2_EMAIL self.create_user(TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS, TEST_USER_ADMIN_EMAIL, True) self.create_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, TEST_USER_REGULAR_EMAIL, False) self.create_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS, TEST_USER_REGULAR2_EMAIL, False) def create_ui_settings(self): """ Creates ui settings, fills out hooks and disables dotencode """ #HOOKS hooks1_key = RhodeCodeUi.HOOK_UPDATE hooks1_ = self.sa.query(RhodeCodeUi)\ .filter(RhodeCodeUi.ui_key == hooks1_key).scalar() hooks1 = RhodeCodeUi() if hooks1_ is None else hooks1_ hooks1.ui_section = 'hooks' hooks1.ui_key = hooks1_key hooks1.ui_value = 'hg update >&2' hooks1.ui_active = False self.sa.add(hooks1) hooks2_key = RhodeCodeUi.HOOK_REPO_SIZE hooks2_ = self.sa.query(RhodeCodeUi)\ .filter(RhodeCodeUi.ui_key == hooks2_key).scalar() hooks2 = RhodeCodeUi() if hooks2_ is None else hooks2_ hooks2.ui_section = 'hooks' hooks2.ui_key = hooks2_key hooks2.ui_value = 'python:rhodecode.lib.hooks.repo_size' self.sa.add(hooks2) hooks3 = RhodeCodeUi() hooks3.ui_section = 'hooks' hooks3.ui_key = RhodeCodeUi.HOOK_PUSH hooks3.ui_value = 'python:rhodecode.lib.hooks.log_push_action' self.sa.add(hooks3) hooks4 = RhodeCodeUi() hooks4.ui_section = 'hooks' hooks4.ui_key = RhodeCodeUi.HOOK_PRE_PUSH hooks4.ui_value = 'python:rhodecode.lib.hooks.pre_push' self.sa.add(hooks4) hooks5 = RhodeCodeUi() hooks5.ui_section = 'hooks' hooks5.ui_key = RhodeCodeUi.HOOK_PULL hooks5.ui_value = 'python:rhodecode.lib.hooks.log_pull_action' self.sa.add(hooks5) hooks6 = RhodeCodeUi() hooks6.ui_section = 'hooks' hooks6.ui_key = RhodeCodeUi.HOOK_PRE_PULL hooks6.ui_value = 'python:rhodecode.lib.hooks.pre_pull' self.sa.add(hooks6) # enable largefiles largefiles = RhodeCodeUi() largefiles.ui_section = 'extensions' largefiles.ui_key = 'largefiles' largefiles.ui_value = '' self.sa.add(largefiles) # enable hgsubversion disabled by default hgsubversion = RhodeCodeUi() hgsubversion.ui_section = 'extensions' hgsubversion.ui_key = 'hgsubversion' hgsubversion.ui_value = '' hgsubversion.ui_active = False self.sa.add(hgsubversion) # enable hggit disabled by default hggit = RhodeCodeUi() hggit.ui_section = 'extensions' hggit.ui_key = 'hggit' hggit.ui_value = '' hggit.ui_active = False self.sa.add(hggit) def create_ldap_options(self, skip_existing=False): """Creates ldap settings""" for k, v in [('ldap_active', 'false'), ('ldap_host', ''), ('ldap_port', '389'), ('ldap_tls_kind', 'PLAIN'), ('ldap_tls_reqcert', ''), ('ldap_dn_user', ''), ('ldap_dn_pass', ''), ('ldap_base_dn', ''), ('ldap_filter', ''), ('ldap_search_scope', ''), ('ldap_attr_login', ''), ('ldap_attr_firstname', ''), ('ldap_attr_lastname', ''), ('ldap_attr_email', '')]: if skip_existing and RhodeCodeSetting.get_by_name(k) is not None: log.debug('Skipping option %s' % k) continue setting = RhodeCodeSetting(k, v) self.sa.add(setting) def create_default_options(self, skip_existing=False): """Creates default settings""" for k, v in [('default_repo_enable_locking', False), ('default_repo_enable_downloads', False), ('default_repo_enable_statistics', False), ('default_repo_private', False), ('default_repo_type', 'hg')]: if skip_existing and RhodeCodeSetting.get_by_name(k) is not None: log.debug('Skipping option %s' % k) continue setting = RhodeCodeSetting(k, v) self.sa.add(setting) def fixup_groups(self): def_usr = User.get_default_user() for g in RepoGroup.query().all(): g.group_name = g.get_new_name(g.name) self.sa.add(g) # get default perm default = UserRepoGroupToPerm.query()\ .filter(UserRepoGroupToPerm.group == g)\ .filter(UserRepoGroupToPerm.user == def_usr)\ .scalar() if default is None: log.debug('missing default permission for group %s adding' % g) perm_obj = ReposGroupModel()._create_default_perms(g) self.sa.add(perm_obj) def reset_permissions(self, username): """ Resets permissions to default state, usefull when old systems had bad permissions, we must clean them up :param username: """ default_user = User.get_by_username(username) if not default_user: return u2p = UserToPerm.query()\ .filter(UserToPerm.user == default_user).all() fixed = False if len(u2p) != len(Permission.DEFAULT_USER_PERMISSIONS): for p in u2p: Session().delete(p) fixed = True self.populate_default_permissions() return fixed def update_repo_info(self): RepoModel.update_repoinfo() def config_prompt(self, test_repo_path='', retries=3): defaults = self.cli_args _path = defaults.get('repos_location') if retries == 3: log.info('Setting up repositories config') if _path is not None: path = _path elif not self.tests and not test_repo_path: path = raw_input( 'Enter a valid absolute path to store repositories. ' 'All repositories in that path will be added automatically:') else: path = test_repo_path path_ok = True # check proper dir if not os.path.isdir(path): path_ok = False log.error('Given path %s is not a valid directory' % (path, )) elif not os.path.isabs(path): path_ok = False log.error('Given path %s is not an absolute path' % (path, )) # check if path is at least readable. if not os.access(path, os.R_OK): path_ok = False log.error('Given path %s is not readable' % (path, )) # check write access, warn user about non writeable paths elif not os.access(path, os.W_OK) and path_ok: log.warn('No write permission to given path %s' % (path, )) if not ask_ok('Given path %s is not writeable, do you want to ' 'continue with read only mode ? [y/n]' % (path, )): log.error('Canceled by user') sys.exit(-1) if retries == 0: sys.exit('max retries reached') if not path_ok: retries -= 1 return self.config_prompt(test_repo_path, retries) real_path = os.path.normpath(os.path.realpath(path)) if real_path != os.path.normpath(path): if not ask_ok(('Path looks like a symlink, Rhodecode will store ' 'given path as %s ? [y/n]') % (real_path, )): log.error('Canceled by user') sys.exit(-1) return real_path def create_settings(self, path): self.create_ui_settings() ui_config = [ ('web', 'push_ssl', 'false'), ('web', 'allow_archive', 'gz zip bz2'), ('web', 'allow_push', '*'), ('web', 'baseurl', '/'), ('paths', '/', path), #('phases', 'publish', 'false') ] for section, key, value in ui_config: ui_conf = RhodeCodeUi() setattr(ui_conf, 'ui_section', section) setattr(ui_conf, 'ui_key', key) setattr(ui_conf, 'ui_value', value) self.sa.add(ui_conf) settings = [('realm', 'RhodeCode authentication', unicode), ('title', 'RhodeCode', unicode), ('ga_code', '', unicode), ('show_public_icon', True, bool), ('show_private_icon', True, bool), ('stylify_metatags', False, bool), ('dashboard_items', 100, int), ('show_version', True, bool)] for key, val, type_ in settings: sett = RhodeCodeSetting(key, val) self.sa.add(sett) self.create_ldap_options() self.create_default_options() log.info('created ui config') def create_user(self, username, password, email='', admin=False): log.info('creating user %s' % username) UserModel().create_or_update(username, password, email, firstname='RhodeCode', lastname='Admin', active=True, admin=admin) def create_default_user(self): log.info('creating default user') # create default user for handling default permissions. user = UserModel().create_or_update(username=User.DEFAULT_USER, password=str(uuid.uuid1())[:20], email='*****@*****.**', firstname='Anonymous', lastname='User') # based on configuration options activate/deactive this user which # controlls anonymous access if self.cli_args.get('public_access') is False: log.info('Public access disabled') user.active = False Session().add(user) Session().commit() def create_permissions(self): """ Creates all permissions defined in the system """ # module.(access|create|change|delete)_[name] # module.(none|read|write|admin) log.info('creating permissions') PermissionModel(self.sa).create_permissions() def populate_default_permissions(self): """ Populate default permissions. It will create only the default permissions that are missing, and not alter already defined ones """ log.info('creating default user permissions') PermissionModel( self.sa).create_default_permissions(user=User.DEFAULT_USER) @staticmethod def check_waitress(): """ Function executed at the end of setup """ if not __py_version__ >= (2, 6): notify('Python2.5 detected, please switch ' 'egg:waitress#main -> egg:Paste#http ' 'in your .ini file')
def tearDown(self): for n in Notification.query().all(): Session.delete(n) Session.commit() self.assertEqual(Notification.query().all(), [])
def _clean_notifications(self): for n in Notification.query().all(): Session.delete(n) Session.commit() self.assertEqual(Notification.query().all(), [])
def authenticate(username, password): """ Authentication function used for access control, firstly checks for db authentication then if ldap is enabled for ldap authentication, also creates ldap user if not in database :param username: username :param password: password """ user_model = UserModel() user = User.get_by_username(username) log.debug('Authenticating user using RhodeCode account') if user is not None and not user.ldap_dn: if user.active: if user.username == 'default' and user.active: log.info('user %s authenticated correctly as anonymous user' % username) return True elif user.username == username and check_password(password, user.password): log.info('user %s authenticated correctly' % username) return True else: log.warning('user %s tried auth but is disabled' % username) else: log.debug('Regular authentication failed') user_obj = User.get_by_username(username, case_insensitive=True) if user_obj is not None and not user_obj.ldap_dn: log.debug('this user already exists as non ldap') return False ldap_settings = RhodeCodeSetting.get_ldap_settings() #====================================================================== # FALLBACK TO LDAP AUTH IF ENABLE #====================================================================== if str2bool(ldap_settings.get('ldap_active')): log.debug("Authenticating user using ldap") kwargs = { 'server': ldap_settings.get('ldap_host', ''), 'base_dn': ldap_settings.get('ldap_base_dn', ''), 'port': ldap_settings.get('ldap_port'), 'bind_dn': ldap_settings.get('ldap_dn_user'), 'bind_pass': ldap_settings.get('ldap_dn_pass'), 'tls_kind': ldap_settings.get('ldap_tls_kind'), 'tls_reqcert': ldap_settings.get('ldap_tls_reqcert'), 'ldap_filter': ldap_settings.get('ldap_filter'), 'search_scope': ldap_settings.get('ldap_search_scope'), 'attr_login': ldap_settings.get('ldap_attr_login'), 'ldap_version': 3, } log.debug('Checking for ldap authentication') try: aldap = AuthLdap(**kwargs) (user_dn, ldap_attrs) = aldap.authenticate_ldap(username, password) log.debug('Got ldap DN response %s' % user_dn) get_ldap_attr = lambda k: ldap_attrs.get(ldap_settings\ .get(k), [''])[0] user_attrs = { 'name': safe_unicode(get_ldap_attr('ldap_attr_firstname')), 'lastname': safe_unicode(get_ldap_attr('ldap_attr_lastname')), 'email': get_ldap_attr('ldap_attr_email'), } # don't store LDAP password since we don't need it. Override # with some random generated password _password = PasswordGenerator().gen_password(length=8) # create this user on the fly if it doesn't exist in rhodecode # database if user_model.create_ldap(username, _password, user_dn, user_attrs): log.info('created new ldap user %s' % username) Session.commit() return True except (LdapUsernameError, LdapPasswordError,): pass except (Exception,): log.error(traceback.format_exc()) pass return False
class DbManage(object): def __init__(self, log_sql, dbconf, root, tests=False, cli_args={}): self.dbname = dbconf.split('/')[-1] self.tests = tests self.root = root self.dburi = dbconf self.log_sql = log_sql self.db_exists = False self.cli_args = cli_args self.init_db() force_ask = self.cli_args.get('force_ask') if force_ask is not None: global ask_ok ask_ok = lambda *args, **kwargs: force_ask def init_db(self): engine = create_engine(self.dburi, echo=self.log_sql) init_model(engine) self.sa = Session() def create_tables(self, override=False): """ Create a auth database """ log.info("Any existing database is going to be destroyed") if self.tests: destroy = True else: destroy = ask_ok('Are you sure to destroy old database ? [y/n]') if not destroy: sys.exit('Nothing done') if destroy: Base.metadata.drop_all() checkfirst = not override Base.metadata.create_all(checkfirst=checkfirst) log.info('Created tables for %s' % self.dbname) def set_db_version(self): ver = DbMigrateVersion() ver.version = __dbversion__ ver.repository_id = 'rhodecode_db_migrations' ver.repository_path = 'versions' self.sa.add(ver) log.info('db version set to: %s' % __dbversion__) def upgrade(self): """ Upgrades given database schema to given revision following all needed steps, to perform the upgrade """ from rhodecode.lib.dbmigrate.migrate.versioning import api from rhodecode.lib.dbmigrate.migrate.exceptions import \ DatabaseNotControlledError if 'sqlite' in self.dburi: print ( '********************** WARNING **********************\n' 'Make sure your version of sqlite is at least 3.7.X. \n' 'Earlier versions are known to fail on some migrations\n' '*****************************************************\n' ) upgrade = ask_ok('You are about to perform database upgrade, make ' 'sure You backed up your database before. ' 'Continue ? [y/n]') if not upgrade: sys.exit('Nothing done') repository_path = jn(dn(dn(dn(os.path.realpath(__file__)))), 'rhodecode/lib/dbmigrate') db_uri = self.dburi try: curr_version = api.db_version(db_uri, repository_path) msg = ('Found current database under version' ' control with version %s' % curr_version) except (RuntimeError, DatabaseNotControlledError): curr_version = 1 msg = ('Current database is not under version control. Setting' ' as version %s' % curr_version) api.version_control(db_uri, repository_path, curr_version) notify(msg) if curr_version == __dbversion__: sys.exit('This database is already at the newest version') #====================================================================== # UPGRADE STEPS #====================================================================== class UpgradeSteps(object): """ Those steps follow schema versions so for example schema for example schema with seq 002 == step_2 and so on. """ def __init__(self, klass): self.klass = klass def step_0(self): # step 0 is the schema upgrade, and than follow proper upgrades notify('attempting to do database upgrade from ' 'version %s to version %s' %(curr_version, __dbversion__)) api.upgrade(db_uri, repository_path, __dbversion__) notify('Schema upgrade completed') def step_1(self): pass def step_2(self): notify('Patching repo paths for newer version of RhodeCode') self.klass.fix_repo_paths() notify('Patching default user of RhodeCode') self.klass.fix_default_user() log.info('Changing ui settings') self.klass.create_ui_settings() def step_3(self): notify('Adding additional settings into RhodeCode db') self.klass.fix_settings() notify('Adding ldap defaults') self.klass.create_ldap_options(skip_existing=True) def step_4(self): notify('create permissions and fix groups') self.klass.create_permissions() self.klass.fixup_groups() def step_5(self): pass def step_6(self): notify('re-checking permissions') self.klass.create_permissions() notify('installing new UI options') sett4 = RhodeCodeSetting('show_public_icon', True) Session().add(sett4) sett5 = RhodeCodeSetting('show_private_icon', True) Session().add(sett5) sett6 = RhodeCodeSetting('stylify_metatags', False) Session().add(sett6) notify('fixing old PULL hook') _pull = RhodeCodeUi.get_by_key('preoutgoing.pull_logger') if _pull: _pull.ui_key = RhodeCodeUi.HOOK_PULL Session().add(_pull) notify('fixing old PUSH hook') _push = RhodeCodeUi.get_by_key('pretxnchangegroup.push_logger') if _push: _push.ui_key = RhodeCodeUi.HOOK_PUSH Session().add(_push) notify('installing new pre-push hook') hooks4 = RhodeCodeUi() hooks4.ui_section = 'hooks' hooks4.ui_key = RhodeCodeUi.HOOK_PRE_PUSH hooks4.ui_value = 'python:rhodecode.lib.hooks.pre_push' Session().add(hooks4) notify('installing new pre-pull hook') hooks6 = RhodeCodeUi() hooks6.ui_section = 'hooks' hooks6.ui_key = RhodeCodeUi.HOOK_PRE_PULL hooks6.ui_value = 'python:rhodecode.lib.hooks.pre_pull' Session().add(hooks6) notify('installing hgsubversion option') # enable hgsubversion disabled by default hgsubversion = RhodeCodeUi() hgsubversion.ui_section = 'extensions' hgsubversion.ui_key = 'hgsubversion' hgsubversion.ui_value = '' hgsubversion.ui_active = False Session().add(hgsubversion) notify('installing hg git option') # enable hggit disabled by default hggit = RhodeCodeUi() hggit.ui_section = 'extensions' hggit.ui_key = 'hggit' hggit.ui_value = '' hggit.ui_active = False Session().add(hggit) notify('re-check default permissions') default_user = User.get_by_username(User.DEFAULT_USER) perm = Permission.get_by_key('hg.fork.repository') reg_perm = UserToPerm() reg_perm.user = default_user reg_perm.permission = perm Session().add(reg_perm) def step_7(self): perm_fixes = self.klass.reset_permissions(User.DEFAULT_USER) Session().commit() if perm_fixes: notify('There was an inconsistent state of permissions ' 'detected for default user. Permissions are now ' 'reset to the default value for default user. ' 'Please validate and check default permissions ' 'in admin panel') def step_8(self): self.klass.populate_default_permissions() self.klass.create_default_options(skip_existing=True) Session().commit() def step_9(self): perm_fixes = self.klass.reset_permissions(User.DEFAULT_USER) Session().commit() if perm_fixes: notify('There was an inconsistent state of permissions ' 'detected for default user. Permissions are now ' 'reset to the default value for default user. ' 'Please validate and check default permissions ' 'in admin panel') def step_10(self): pass def step_11(self): self.klass.update_repo_info() upgrade_steps = [0] + range(curr_version + 1, __dbversion__ + 1) # CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE _step = None for step in upgrade_steps: notify('performing upgrade step %s' % step) getattr(UpgradeSteps(self), 'step_%s' % step)() self.sa.commit() _step = step notify('upgrade to version %s successful' % _step) def fix_repo_paths(self): """ Fixes a old rhodecode version path into new one without a '*' """ paths = self.sa.query(RhodeCodeUi)\ .filter(RhodeCodeUi.ui_key == '/')\ .scalar() paths.ui_value = paths.ui_value.replace('*', '') try: self.sa.add(paths) self.sa.commit() except Exception: self.sa.rollback() raise def fix_default_user(self): """ Fixes a old default user with some 'nicer' default values, used mostly for anonymous access """ def_user = self.sa.query(User)\ .filter(User.username == 'default')\ .one() def_user.name = 'Anonymous' def_user.lastname = 'User' def_user.email = '*****@*****.**' try: self.sa.add(def_user) self.sa.commit() except Exception: self.sa.rollback() raise def fix_settings(self): """ Fixes rhodecode settings adds ga_code key for google analytics """ hgsettings3 = RhodeCodeSetting('ga_code', '') try: self.sa.add(hgsettings3) self.sa.commit() except Exception: self.sa.rollback() raise def admin_prompt(self, second=False): if not self.tests: import getpass # defaults defaults = self.cli_args username = defaults.get('username') password = defaults.get('password') email = defaults.get('email') def get_password(): password = getpass.getpass('Specify admin password ' '(min 6 chars):') confirm = getpass.getpass('Confirm password:'******'passwords mismatch') return False if len(password) < 6: log.error('password is to short use at least 6 characters') return False return password if username is None: username = raw_input('Specify admin username:'******'Specify admin email:') self.create_user(username, password, email, True) else: log.info('creating admin and regular test users') from rhodecode.tests import TEST_USER_ADMIN_LOGIN, \ TEST_USER_ADMIN_PASS, TEST_USER_ADMIN_EMAIL, \ TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, \ TEST_USER_REGULAR_EMAIL, TEST_USER_REGULAR2_LOGIN, \ TEST_USER_REGULAR2_PASS, TEST_USER_REGULAR2_EMAIL self.create_user(TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS, TEST_USER_ADMIN_EMAIL, True) self.create_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, TEST_USER_REGULAR_EMAIL, False) self.create_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS, TEST_USER_REGULAR2_EMAIL, False) def create_ui_settings(self): """ Creates ui settings, fills out hooks and disables dotencode """ #HOOKS hooks1_key = RhodeCodeUi.HOOK_UPDATE hooks1_ = self.sa.query(RhodeCodeUi)\ .filter(RhodeCodeUi.ui_key == hooks1_key).scalar() hooks1 = RhodeCodeUi() if hooks1_ is None else hooks1_ hooks1.ui_section = 'hooks' hooks1.ui_key = hooks1_key hooks1.ui_value = 'hg update >&2' hooks1.ui_active = False self.sa.add(hooks1) hooks2_key = RhodeCodeUi.HOOK_REPO_SIZE hooks2_ = self.sa.query(RhodeCodeUi)\ .filter(RhodeCodeUi.ui_key == hooks2_key).scalar() hooks2 = RhodeCodeUi() if hooks2_ is None else hooks2_ hooks2.ui_section = 'hooks' hooks2.ui_key = hooks2_key hooks2.ui_value = 'python:rhodecode.lib.hooks.repo_size' self.sa.add(hooks2) hooks3 = RhodeCodeUi() hooks3.ui_section = 'hooks' hooks3.ui_key = RhodeCodeUi.HOOK_PUSH hooks3.ui_value = 'python:rhodecode.lib.hooks.log_push_action' self.sa.add(hooks3) hooks4 = RhodeCodeUi() hooks4.ui_section = 'hooks' hooks4.ui_key = RhodeCodeUi.HOOK_PRE_PUSH hooks4.ui_value = 'python:rhodecode.lib.hooks.pre_push' self.sa.add(hooks4) hooks5 = RhodeCodeUi() hooks5.ui_section = 'hooks' hooks5.ui_key = RhodeCodeUi.HOOK_PULL hooks5.ui_value = 'python:rhodecode.lib.hooks.log_pull_action' self.sa.add(hooks5) hooks6 = RhodeCodeUi() hooks6.ui_section = 'hooks' hooks6.ui_key = RhodeCodeUi.HOOK_PRE_PULL hooks6.ui_value = 'python:rhodecode.lib.hooks.pre_pull' self.sa.add(hooks6) # enable largefiles largefiles = RhodeCodeUi() largefiles.ui_section = 'extensions' largefiles.ui_key = 'largefiles' largefiles.ui_value = '' self.sa.add(largefiles) # enable hgsubversion disabled by default hgsubversion = RhodeCodeUi() hgsubversion.ui_section = 'extensions' hgsubversion.ui_key = 'hgsubversion' hgsubversion.ui_value = '' hgsubversion.ui_active = False self.sa.add(hgsubversion) # enable hggit disabled by default hggit = RhodeCodeUi() hggit.ui_section = 'extensions' hggit.ui_key = 'hggit' hggit.ui_value = '' hggit.ui_active = False self.sa.add(hggit) def create_ldap_options(self, skip_existing=False): """Creates ldap settings""" for k, v in [('ldap_active', 'false'), ('ldap_host', ''), ('ldap_port', '389'), ('ldap_tls_kind', 'PLAIN'), ('ldap_tls_reqcert', ''), ('ldap_dn_user', ''), ('ldap_dn_pass', ''), ('ldap_base_dn', ''), ('ldap_filter', ''), ('ldap_search_scope', ''), ('ldap_attr_login', ''), ('ldap_attr_firstname', ''), ('ldap_attr_lastname', ''), ('ldap_attr_email', '')]: if skip_existing and RhodeCodeSetting.get_by_name(k) != None: log.debug('Skipping option %s' % k) continue setting = RhodeCodeSetting(k, v) self.sa.add(setting) def create_default_options(self, skip_existing=False): """Creates default settings""" for k, v in [ ('default_repo_enable_locking', False), ('default_repo_enable_downloads', False), ('default_repo_enable_statistics', False), ('default_repo_private', False), ('default_repo_type', 'hg')]: if skip_existing and RhodeCodeSetting.get_by_name(k) != None: log.debug('Skipping option %s' % k) continue setting = RhodeCodeSetting(k, v) self.sa.add(setting) def fixup_groups(self): def_usr = User.get_by_username('default') for g in RepoGroup.query().all(): g.group_name = g.get_new_name(g.name) self.sa.add(g) # get default perm default = UserRepoGroupToPerm.query()\ .filter(UserRepoGroupToPerm.group == g)\ .filter(UserRepoGroupToPerm.user == def_usr)\ .scalar() if default is None: log.debug('missing default permission for group %s adding' % g) ReposGroupModel()._create_default_perms(g) def reset_permissions(self, username): """ Resets permissions to default state, usefull when old systems had bad permissions, we must clean them up :param username: :type username: """ default_user = User.get_by_username(username) if not default_user: return u2p = UserToPerm.query()\ .filter(UserToPerm.user == default_user).all() fixed = False if len(u2p) != len(User.DEFAULT_PERMISSIONS): for p in u2p: Session().delete(p) fixed = True self.populate_default_permissions() return fixed def update_repo_info(self): RepoModel.update_repoinfo() def config_prompt(self, test_repo_path='', retries=3): defaults = self.cli_args _path = defaults.get('repos_location') if retries == 3: log.info('Setting up repositories config') if _path is not None: path = _path elif not self.tests and not test_repo_path: path = raw_input( 'Enter a valid absolute path to store repositories. ' 'All repositories in that path will be added automatically:' ) else: path = test_repo_path path_ok = True # check proper dir if not os.path.isdir(path): path_ok = False log.error('Given path %s is not a valid directory' % path) elif not os.path.isabs(path): path_ok = False log.error('Given path %s is not an absolute path' % path) # check write access elif not os.access(path, os.W_OK) and path_ok: path_ok = False log.error('No write permission to given path %s' % path) if retries == 0: sys.exit('max retries reached') if not path_ok: retries -= 1 return self.config_prompt(test_repo_path, retries) real_path = os.path.normpath(os.path.realpath(path)) if real_path != os.path.normpath(path): if not ask_ok(('Path looks like a symlink, Rhodecode will store ' 'given path as %s ? [y/n]') % (real_path)): log.error('Canceled by user') sys.exit(-1) return real_path def create_settings(self, path): self.create_ui_settings() #HG UI OPTIONS web1 = RhodeCodeUi() web1.ui_section = 'web' web1.ui_key = 'push_ssl' web1.ui_value = 'false' web2 = RhodeCodeUi() web2.ui_section = 'web' web2.ui_key = 'allow_archive' web2.ui_value = 'gz zip bz2' web3 = RhodeCodeUi() web3.ui_section = 'web' web3.ui_key = 'allow_push' web3.ui_value = '*' web4 = RhodeCodeUi() web4.ui_section = 'web' web4.ui_key = 'baseurl' web4.ui_value = '/' paths = RhodeCodeUi() paths.ui_section = 'paths' paths.ui_key = '/' paths.ui_value = path phases = RhodeCodeUi() phases.ui_section = 'phases' phases.ui_key = 'publish' phases.ui_value = False sett1 = RhodeCodeSetting('realm', 'RhodeCode authentication') sett2 = RhodeCodeSetting('title', 'RhodeCode') sett3 = RhodeCodeSetting('ga_code', '') sett4 = RhodeCodeSetting('show_public_icon', True) sett5 = RhodeCodeSetting('show_private_icon', True) sett6 = RhodeCodeSetting('stylify_metatags', False) self.sa.add(web1) self.sa.add(web2) self.sa.add(web3) self.sa.add(web4) self.sa.add(paths) self.sa.add(sett1) self.sa.add(sett2) self.sa.add(sett3) self.sa.add(sett4) self.sa.add(sett5) self.sa.add(sett6) self.create_ldap_options() self.create_default_options() log.info('created ui config') def create_user(self, username, password, email='', admin=False): log.info('creating user %s' % username) UserModel().create_or_update(username, password, email, firstname='RhodeCode', lastname='Admin', active=True, admin=admin) def create_default_user(self): log.info('creating default user') # create default user for handling default permissions. UserModel().create_or_update(username='******', password=str(uuid.uuid1())[:8], email='*****@*****.**', firstname='Anonymous', lastname='User') def create_permissions(self): # module.(access|create|change|delete)_[name] # module.(none|read|write|admin) for p in Permission.PERMS: if not Permission.get_by_key(p[0]): new_perm = Permission() new_perm.permission_name = p[0] new_perm.permission_longname = p[0] self.sa.add(new_perm) def populate_default_permissions(self): log.info('creating default user permissions') default_user = User.get_by_username('default') for def_perm in User.DEFAULT_PERMISSIONS: perm = self.sa.query(Permission)\ .filter(Permission.permission_name == def_perm)\ .scalar() if not perm: raise Exception( 'CRITICAL: permission %s not found inside database !!' % def_perm ) if not UserToPerm.query()\ .filter(UserToPerm.permission == perm)\ .filter(UserToPerm.user == default_user).scalar(): reg_perm = UserToPerm() reg_perm.user = default_user reg_perm.permission = perm self.sa.add(reg_perm) @staticmethod def check_waitress(): """ Function executed at the end of setup """ if not __py_version__ >= (2, 6): notify('Python2.5 detected, please switch ' 'egg:waitress#main -> egg:Paste#http ' 'in your .ini file')
class DbManage(object): def __init__(self, log_sql, dbconf, root, tests=False, SESSION=None, cli_args={}): self.dbname = dbconf.split('/')[-1] self.tests = tests self.root = root self.dburi = dbconf self.log_sql = log_sql self.db_exists = False self.cli_args = cli_args self.init_db(SESSION=SESSION) self.ask_ok = self.get_ask_ok_func(self.cli_args.get('force_ask')) def get_ask_ok_func(self, param): if param not in [None]: # return a function lambda that has a default set to param return lambda *args, **kwargs: param else: from rhodecode.lib.utils import ask_ok return ask_ok def init_db(self, SESSION=None): if SESSION: self.sa = SESSION else: # init new sessions engine = create_engine(self.dburi, echo=self.log_sql) init_model(engine) self.sa = Session() def create_tables(self, override=False): """ Create a auth database """ log.info("Existing database with the same name is going to be destroyed.") log.info("Setup command will run DROP ALL command on that database.") if self.tests: destroy = True else: destroy = self.ask_ok('Are you sure that you want to destroy the old database? [y/n]') if not destroy: log.info('Nothing done.') sys.exit(0) if destroy: Base.metadata.drop_all() checkfirst = not override Base.metadata.create_all(checkfirst=checkfirst) log.info('Created tables for %s' % self.dbname) def set_db_version(self): ver = DbMigrateVersion() ver.version = __dbversion__ ver.repository_id = 'rhodecode_db_migrations' ver.repository_path = 'versions' self.sa.add(ver) log.info('db version set to: %s' % __dbversion__) def run_pre_migration_tasks(self): """ Run various tasks before actually doing migrations """ # delete cache keys on each upgrade total = CacheKey.query().count() log.info("Deleting (%s) cache keys now...", total) CacheKey.delete_all_cache() def upgrade(self): """ Upgrades given database schema to given revision following all needed steps, to perform the upgrade """ from rhodecode.lib.dbmigrate.migrate.versioning import api from rhodecode.lib.dbmigrate.migrate.exceptions import \ DatabaseNotControlledError if 'sqlite' in self.dburi: print ( '********************** WARNING **********************\n' 'Make sure your version of sqlite is at least 3.7.X. \n' 'Earlier versions are known to fail on some migrations\n' '*****************************************************\n') upgrade = self.ask_ok( 'You are about to perform a database upgrade. Make ' 'sure you have backed up your database. ' 'Continue ? [y/n]') if not upgrade: log.info('No upgrade performed') sys.exit(0) repository_path = jn(dn(dn(dn(os.path.realpath(__file__)))), 'rhodecode/lib/dbmigrate') db_uri = self.dburi try: curr_version = api.db_version(db_uri, repository_path) msg = ('Found current database under version ' 'control with version %s' % curr_version) except (RuntimeError, DatabaseNotControlledError): curr_version = 1 msg = ('Current database is not under version control. Setting ' 'as version %s' % curr_version) api.version_control(db_uri, repository_path, curr_version) notify(msg) self.run_pre_migration_tasks() if curr_version == __dbversion__: log.info('This database is already at the newest version') sys.exit(0) upgrade_steps = range(curr_version + 1, __dbversion__ + 1) notify('attempting to upgrade database from ' 'version %s to version %s' % (curr_version, __dbversion__)) # CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE _step = None for step in upgrade_steps: notify('performing upgrade step %s' % step) time.sleep(0.5) api.upgrade(db_uri, repository_path, step) self.sa.rollback() notify('schema upgrade for step %s completed' % (step,)) _step = step notify('upgrade to version %s successful' % _step) def fix_repo_paths(self): """ Fixes an old RhodeCode version path into new one without a '*' """ paths = self.sa.query(RhodeCodeUi)\ .filter(RhodeCodeUi.ui_key == '/')\ .scalar() paths.ui_value = paths.ui_value.replace('*', '') try: self.sa.add(paths) self.sa.commit() except Exception: self.sa.rollback() raise def fix_default_user(self): """ Fixes an old default user with some 'nicer' default values, used mostly for anonymous access """ def_user = self.sa.query(User)\ .filter(User.username == User.DEFAULT_USER)\ .one() def_user.name = 'Anonymous' def_user.lastname = 'User' def_user.email = User.DEFAULT_USER_EMAIL try: self.sa.add(def_user) self.sa.commit() except Exception: self.sa.rollback() raise def fix_settings(self): """ Fixes rhodecode settings and adds ga_code key for google analytics """ hgsettings3 = RhodeCodeSetting('ga_code', '') try: self.sa.add(hgsettings3) self.sa.commit() except Exception: self.sa.rollback() raise def create_admin_and_prompt(self): # defaults defaults = self.cli_args username = defaults.get('username') password = defaults.get('password') email = defaults.get('email') if username is None: username = raw_input('Specify admin username:'******'Specify admin email:') api_key = self.cli_args.get('api_key') self.create_user(username, password, email, True, strict_creation_check=False, api_key=api_key) def _get_admin_password(self): password = getpass.getpass('Specify admin password ' '(min 6 chars):') confirm = getpass.getpass('Confirm password:'******'passwords mismatch') return False if len(password) < 6: log.error('password is too short - use at least 6 characters') return False return password def create_test_admin_and_users(self): log.info('creating admin and regular test users') from rhodecode.tests import TEST_USER_ADMIN_LOGIN, \ TEST_USER_ADMIN_PASS, TEST_USER_ADMIN_EMAIL, \ TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, \ TEST_USER_REGULAR_EMAIL, TEST_USER_REGULAR2_LOGIN, \ TEST_USER_REGULAR2_PASS, TEST_USER_REGULAR2_EMAIL self.create_user(TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS, TEST_USER_ADMIN_EMAIL, True) self.create_user(TEST_USER_REGULAR_LOGIN, TEST_USER_REGULAR_PASS, TEST_USER_REGULAR_EMAIL, False) self.create_user(TEST_USER_REGULAR2_LOGIN, TEST_USER_REGULAR2_PASS, TEST_USER_REGULAR2_EMAIL, False) def create_ui_settings(self, repo_store_path): """ Creates ui settings, fills out hooks and disables dotencode """ settings_model = SettingsModel(sa=self.sa) # Build HOOKS hooks = [ (RhodeCodeUi.HOOK_REPO_SIZE, 'python:vcsserver.hooks.repo_size'), # HG (RhodeCodeUi.HOOK_PRE_PULL, 'python:vcsserver.hooks.pre_pull'), (RhodeCodeUi.HOOK_PULL, 'python:vcsserver.hooks.log_pull_action'), (RhodeCodeUi.HOOK_PRE_PUSH, 'python:vcsserver.hooks.pre_push'), (RhodeCodeUi.HOOK_PUSH, 'python:vcsserver.hooks.log_push_action'), ] for key, value in hooks: hook_obj = settings_model.get_ui_by_key(key) hooks2 = hook_obj if hook_obj else RhodeCodeUi() hooks2.ui_section = 'hooks' hooks2.ui_key = key hooks2.ui_value = value self.sa.add(hooks2) # enable largefiles largefiles = RhodeCodeUi() largefiles.ui_section = 'extensions' largefiles.ui_key = 'largefiles' largefiles.ui_value = '' self.sa.add(largefiles) # set default largefiles cache dir, defaults to # /repo location/.cache/largefiles largefiles = RhodeCodeUi() largefiles.ui_section = 'largefiles' largefiles.ui_key = 'usercache' largefiles.ui_value = os.path.join(repo_store_path, '.cache', 'largefiles') self.sa.add(largefiles) # enable hgsubversion disabled by default hgsubversion = RhodeCodeUi() hgsubversion.ui_section = 'extensions' hgsubversion.ui_key = 'hgsubversion' hgsubversion.ui_value = '' hgsubversion.ui_active = False self.sa.add(hgsubversion) # enable hggit disabled by default hggit = RhodeCodeUi() hggit.ui_section = 'extensions' hggit.ui_key = 'hggit' hggit.ui_value = '' hggit.ui_active = False self.sa.add(hggit) # set svn branch defaults branches = ["/branches/*", "/trunk"] tags = ["/tags/*"] for branch in branches: settings_model.create_ui_section_value( RhodeCodeUi.SVN_BRANCH_ID, branch) for tag in tags: settings_model.create_ui_section_value(RhodeCodeUi.SVN_TAG_ID, tag) def create_auth_plugin_options(self, skip_existing=False): """ Create default auth plugin settings, and make it active :param skip_existing: """ for k, v, t in [('auth_plugins', 'egg:rhodecode-enterprise-ce#rhodecode', 'list'), ('auth_rhodecode_enabled', 'True', 'bool')]: if (skip_existing and SettingsModel().get_setting_by_name(k) is not None): log.debug('Skipping option %s' % k) continue setting = RhodeCodeSetting(k, v, t) self.sa.add(setting) def create_default_options(self, skip_existing=False): """Creates default settings""" for k, v, t in [ ('default_repo_enable_locking', False, 'bool'), ('default_repo_enable_downloads', False, 'bool'), ('default_repo_enable_statistics', False, 'bool'), ('default_repo_private', False, 'bool'), ('default_repo_type', 'hg', 'unicode')]: if (skip_existing and SettingsModel().get_setting_by_name(k) is not None): log.debug('Skipping option %s' % k) continue setting = RhodeCodeSetting(k, v, t) self.sa.add(setting) def fixup_groups(self): def_usr = User.get_default_user() for g in RepoGroup.query().all(): g.group_name = g.get_new_name(g.name) self.sa.add(g) # get default perm default = UserRepoGroupToPerm.query()\ .filter(UserRepoGroupToPerm.group == g)\ .filter(UserRepoGroupToPerm.user == def_usr)\ .scalar() if default is None: log.debug('missing default permission for group %s adding' % g) perm_obj = RepoGroupModel()._create_default_perms(g) self.sa.add(perm_obj) def reset_permissions(self, username): """ Resets permissions to default state, useful when old systems had bad permissions, we must clean them up :param username: """ default_user = User.get_by_username(username) if not default_user: return u2p = UserToPerm.query()\ .filter(UserToPerm.user == default_user).all() fixed = False if len(u2p) != len(Permission.DEFAULT_USER_PERMISSIONS): for p in u2p: Session().delete(p) fixed = True self.populate_default_permissions() return fixed def update_repo_info(self): RepoModel.update_repoinfo() def config_prompt(self, test_repo_path='', retries=3): defaults = self.cli_args _path = defaults.get('repos_location') if retries == 3: log.info('Setting up repositories config') if _path is not None: path = _path elif not self.tests and not test_repo_path: path = raw_input( 'Enter a valid absolute path to store repositories. ' 'All repositories in that path will be added automatically:' ) else: path = test_repo_path path_ok = True # check proper dir if not os.path.isdir(path): path_ok = False log.error('Given path %s is not a valid directory' % (path,)) elif not os.path.isabs(path): path_ok = False log.error('Given path %s is not an absolute path' % (path,)) # check if path is at least readable. if not os.access(path, os.R_OK): path_ok = False log.error('Given path %s is not readable' % (path,)) # check write access, warn user about non writeable paths elif not os.access(path, os.W_OK) and path_ok: log.warning('No write permission to given path %s' % (path,)) q = ('Given path %s is not writeable, do you want to ' 'continue with read only mode ? [y/n]' % (path,)) if not self.ask_ok(q): log.error('Canceled by user') sys.exit(-1) if retries == 0: sys.exit('max retries reached') if not path_ok: retries -= 1 return self.config_prompt(test_repo_path, retries) real_path = os.path.normpath(os.path.realpath(path)) if real_path != os.path.normpath(path): q = ('Path looks like a symlink, RhodeCode Enterprise will store ' 'given path as %s ? [y/n]') % (real_path,) if not self.ask_ok(q): log.error('Canceled by user') sys.exit(-1) return real_path def create_settings(self, path): self.create_ui_settings(path) ui_config = [ ('web', 'push_ssl', 'false'), ('web', 'allow_archive', 'gz zip bz2'), ('web', 'allow_push', '*'), ('web', 'baseurl', '/'), ('paths', '/', path), ('phases', 'publish', 'true') ] for section, key, value in ui_config: ui_conf = RhodeCodeUi() setattr(ui_conf, 'ui_section', section) setattr(ui_conf, 'ui_key', key) setattr(ui_conf, 'ui_value', value) self.sa.add(ui_conf) # rhodecode app settings settings = [ ('realm', 'RhodeCode', 'unicode'), ('title', '', 'unicode'), ('pre_code', '', 'unicode'), ('post_code', '', 'unicode'), ('show_public_icon', True, 'bool'), ('show_private_icon', True, 'bool'), ('stylify_metatags', False, 'bool'), ('dashboard_items', 100, 'int'), ('admin_grid_items', 25, 'int'), ('show_version', True, 'bool'), ('use_gravatar', False, 'bool'), ('gravatar_url', User.DEFAULT_GRAVATAR_URL, 'unicode'), ('clone_uri_tmpl', Repository.DEFAULT_CLONE_URI, 'unicode'), ('support_url', '', 'unicode'), ('update_url', RhodeCodeSetting.DEFAULT_UPDATE_URL, 'unicode'), ('show_revision_number', True, 'bool'), ('show_sha_length', 12, 'int'), ] for key, val, type_ in settings: sett = RhodeCodeSetting(key, val, type_) self.sa.add(sett) self.create_auth_plugin_options() self.create_default_options() log.info('created ui config') def create_user(self, username, password, email='', admin=False, strict_creation_check=True, api_key=None): log.info('creating user %s' % username) user = UserModel().create_or_update( username, password, email, firstname='RhodeCode', lastname='Admin', active=True, admin=admin, extern_type="rhodecode", strict_creation_check=strict_creation_check) if api_key: log.info('setting a provided api key for the user %s', username) user.api_key = api_key def create_default_user(self): log.info('creating default user') # create default user for handling default permissions. user = UserModel().create_or_update(username=User.DEFAULT_USER, password=str(uuid.uuid1())[:20], email=User.DEFAULT_USER_EMAIL, firstname='Anonymous', lastname='User', strict_creation_check=False) # based on configuration options activate/deactive this user which # controlls anonymous access if self.cli_args.get('public_access') is False: log.info('Public access disabled') user.active = False Session().add(user) Session().commit() def create_permissions(self): """ Creates all permissions defined in the system """ # module.(access|create|change|delete)_[name] # module.(none|read|write|admin) log.info('creating permissions') PermissionModel(self.sa).create_permissions() def populate_default_permissions(self): """ Populate default permissions. It will create only the default permissions that are missing, and not alter already defined ones """ log.info('creating default user permissions') PermissionModel(self.sa).create_default_user_permissions(user=User.DEFAULT_USER)
def delete(cls, id_): obj = cls.query().get(id_) Session.delete(obj) Session.commit()
class AuthnPluginViewBase(object): def __init__(self, context, request): self.request = request self.context = context self.plugin = context.plugin self._rhodecode_user = request.user @LoginRequired() @HasPermissionAllDecorator('hg.admin') def settings_get(self, defaults=None, errors=None): """ View that displays the plugin settings as a form. """ defaults = defaults or {} errors = errors or {} schema = self.plugin.get_settings_schema() # Compute default values for the form. Priority is: # 1. Passed to this method 2. DB value 3. Schema default for node in schema: if node.name not in defaults: defaults[node.name] = self.plugin.get_setting_by_name( node.name, node.default) template_context = { 'defaults': defaults, 'errors': errors, 'plugin': self.context.plugin, 'resource': self.context, } return template_context @LoginRequired() @HasPermissionAllDecorator('hg.admin') @auth.CSRFRequired() def settings_post(self): """ View that validates and stores the plugin settings. """ schema = self.plugin.get_settings_schema() data = self.request.params try: valid_data = schema.deserialize(data) except colander.Invalid, e: # Display error message and display form again. self.request.session.flash(_( 'Errors exist when saving plugin settings. ' 'Please check the form inputs.'), queue='error') defaults = {key: data[key] for key in data if key in schema} return self.settings_get(errors=e.asdict(), defaults=defaults) # Store validated data. for name, value in valid_data.items(): self.plugin.create_or_update_setting(name, value) Session.commit() # Display success message and redirect. self.request.session.flash(_('Auth settings updated successfully.'), queue='success') redirect_to = self.request.resource_path(self.context, route_name='auth_home') return HTTPFound(redirect_to)