repo-groups: implemented default personal repo groups logic.
- fixes #4003 - adds new settings to automatically create personal repo groups for users on API cal, add user form, registration - it's possible to create a pattern based repo group for example /u/{username}
This commit is contained in:
parent
922242c2ba
commit
9e6713219c
19 changed files with 240 additions and 56 deletions
|
|
@ -51,7 +51,7 @@ PYRAMID_SETTINGS = {}
|
|||
EXTENSIONS = {}
|
||||
|
||||
__version__ = ('.'.join((str(each) for each in VERSION[:3])))
|
||||
__dbversion__ = 62 # defines current db version for migrations
|
||||
__dbversion__ = 63 # defines current db version for migrations
|
||||
__platform__ = platform.system()
|
||||
__license__ = 'AGPLv3, and Commercial License'
|
||||
__author__ = 'RhodeCode GmbH'
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ from rhodecode.api.utils import (
|
|||
Optional, OAttr, has_superadmin_permission, get_user_or_error, store_update)
|
||||
from rhodecode.lib.auth import AuthUser, PasswordGenerator
|
||||
from rhodecode.lib.exceptions import DefaultUserException
|
||||
from rhodecode.lib.utils2 import safe_int
|
||||
from rhodecode.lib.utils2 import safe_int, str2bool
|
||||
from rhodecode.model.db import Session, User, Repository
|
||||
from rhodecode.model.user import UserModel
|
||||
|
||||
|
|
@ -155,7 +155,8 @@ def create_user(request, apiuser, username, email, password=Optional(''),
|
|||
active=Optional(True), admin=Optional(False),
|
||||
extern_name=Optional('rhodecode'),
|
||||
extern_type=Optional('rhodecode'),
|
||||
force_password_change=Optional(False)):
|
||||
force_password_change=Optional(False),
|
||||
create_personal_repo_group=Optional(None)):
|
||||
"""
|
||||
Creates a new user and returns the new user object.
|
||||
|
||||
|
|
@ -188,7 +189,8 @@ def create_user(request, apiuser, username, email, password=Optional(''),
|
|||
:param force_password_change: Force the new user to change password
|
||||
on next login.
|
||||
:type force_password_change: Optional(``True`` | ``False``)
|
||||
|
||||
:param create_personal_repo_group: Create personal repo group for this user
|
||||
:type create_personal_repo_group: Optional(``True`` | ``False``)
|
||||
Example output:
|
||||
|
||||
.. code-block:: bash
|
||||
|
|
@ -230,6 +232,9 @@ def create_user(request, apiuser, username, email, password=Optional(''),
|
|||
Optional.extract(extern_name) != 'rhodecode'):
|
||||
# generate temporary password if user is external
|
||||
password = PasswordGenerator().gen_password(length=16)
|
||||
create_repo_group = Optional.extract(create_personal_repo_group)
|
||||
if isinstance(create_repo_group, basestring):
|
||||
create_repo_group = str2bool(create_repo_group)
|
||||
|
||||
try:
|
||||
user = UserModel().create_or_update(
|
||||
|
|
@ -243,6 +248,7 @@ def create_user(request, apiuser, username, email, password=Optional(''),
|
|||
extern_type=Optional.extract(extern_type),
|
||||
extern_name=Optional.extract(extern_name),
|
||||
force_password_change=Optional.extract(force_password_change),
|
||||
create_repo_group=create_repo_group
|
||||
)
|
||||
Session().commit()
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -160,6 +160,7 @@ class ReposController(BaseRepoController):
|
|||
self.__load_defaults()
|
||||
form_result = {}
|
||||
task_id = None
|
||||
c.personal_repo_group = c.rhodecode_user.personal_repo_group
|
||||
try:
|
||||
# CanWriteToGroup validators checks permissions of this POST
|
||||
form_result = RepoForm(repo_groups=c.repo_groups_choices,
|
||||
|
|
@ -173,8 +174,6 @@ class ReposController(BaseRepoController):
|
|||
if isinstance(task, BaseAsyncResult):
|
||||
task_id = task.task_id
|
||||
except formencode.Invalid as errors:
|
||||
c.personal_repo_group = RepoGroup.get_by_group_name(
|
||||
c.rhodecode_user.username)
|
||||
return htmlfill.render(
|
||||
render('admin/repos/repo_add.html'),
|
||||
defaults=errors.value,
|
||||
|
|
@ -215,7 +214,7 @@ class ReposController(BaseRepoController):
|
|||
c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
|
||||
c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
|
||||
choices, c.landing_revs = ScmModel().get_repo_landing_revs()
|
||||
c.personal_repo_group = RepoGroup.get_by_group_name(c.rhodecode_user.username)
|
||||
c.personal_repo_group = c.rhodecode_user.personal_repo_group
|
||||
c.new_repo = repo_name_slug(new_repo)
|
||||
|
||||
## apply the defaults from defaults page
|
||||
|
|
@ -299,9 +298,8 @@ class ReposController(BaseRepoController):
|
|||
repo_model = RepoModel()
|
||||
changed_name = repo_name
|
||||
|
||||
c.personal_repo_group = c.rhodecode_user.personal_repo_group
|
||||
# override the choices with extracted revisions !
|
||||
c.personal_repo_group = RepoGroup.get_by_group_name(
|
||||
c.rhodecode_user.username)
|
||||
repo = Repository.get_by_repo_name(repo_name)
|
||||
old_data = {
|
||||
'repo_name': repo_name,
|
||||
|
|
@ -399,8 +397,7 @@ class ReposController(BaseRepoController):
|
|||
|
||||
c.repo_fields = RepositoryField.query()\
|
||||
.filter(RepositoryField.repository == c.repo_info).all()
|
||||
c.personal_repo_group = RepoGroup.get_by_group_name(
|
||||
c.rhodecode_user.username)
|
||||
c.personal_repo_group = c.rhodecode_user.personal_repo_group
|
||||
c.active = 'settings'
|
||||
return htmlfill.render(
|
||||
render('admin/repos/repo_edit.html'),
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ from rhodecode.model.db import RhodeCodeUi, Repository
|
|||
from rhodecode.model.forms import ApplicationSettingsForm, \
|
||||
ApplicationUiSettingsForm, ApplicationVisualisationForm, \
|
||||
LabsSettingsForm, IssueTrackerPatternsForm
|
||||
from rhodecode.model.repo_group import RepoGroupModel
|
||||
|
||||
from rhodecode.model.scm import ScmModel
|
||||
from rhodecode.model.notification import EmailNotificationModel
|
||||
|
|
@ -245,6 +246,8 @@ class SettingsController(BaseController):
|
|||
"""POST /admin/settings/global: All items in the collection"""
|
||||
# url('admin_settings_global')
|
||||
c.active = 'global'
|
||||
c.personal_repo_group_default_pattern = RepoGroupModel()\
|
||||
.get_personal_group_name_pattern()
|
||||
application_form = ApplicationSettingsForm()()
|
||||
try:
|
||||
form_result = application_form.to_python(dict(request.POST))
|
||||
|
|
@ -259,16 +262,18 @@ class SettingsController(BaseController):
|
|||
|
||||
try:
|
||||
settings = [
|
||||
('title', 'rhodecode_title'),
|
||||
('realm', 'rhodecode_realm'),
|
||||
('pre_code', 'rhodecode_pre_code'),
|
||||
('post_code', 'rhodecode_post_code'),
|
||||
('captcha_public_key', 'rhodecode_captcha_public_key'),
|
||||
('captcha_private_key', 'rhodecode_captcha_private_key'),
|
||||
('title', 'rhodecode_title', 'unicode'),
|
||||
('realm', 'rhodecode_realm', 'unicode'),
|
||||
('pre_code', 'rhodecode_pre_code', 'unicode'),
|
||||
('post_code', 'rhodecode_post_code', 'unicode'),
|
||||
('captcha_public_key', 'rhodecode_captcha_public_key', 'unicode'),
|
||||
('captcha_private_key', 'rhodecode_captcha_private_key', 'unicode'),
|
||||
('create_personal_repo_group', 'rhodecode_create_personal_repo_group', 'bool'),
|
||||
('personal_repo_group_pattern', 'rhodecode_personal_repo_group_pattern', 'unicode'),
|
||||
]
|
||||
for setting, form_key in settings:
|
||||
for setting, form_key, type_ in settings:
|
||||
sett = SettingsModel().create_or_update_setting(
|
||||
setting, form_result[form_key])
|
||||
setting, form_result[form_key], type_)
|
||||
Session().add(sett)
|
||||
|
||||
Session().commit()
|
||||
|
|
@ -287,6 +292,8 @@ class SettingsController(BaseController):
|
|||
"""GET /admin/settings/global: All items in the collection"""
|
||||
# url('admin_settings_global')
|
||||
c.active = 'global'
|
||||
c.personal_repo_group_default_pattern = RepoGroupModel()\
|
||||
.get_personal_group_name_pattern()
|
||||
|
||||
return htmlfill.render(
|
||||
render('admin/settings/settings.html'),
|
||||
|
|
|
|||
|
|
@ -45,12 +45,13 @@ from rhodecode.model.db import (
|
|||
PullRequestReviewers, User, UserEmailMap, UserIpMap, RepoGroup)
|
||||
from rhodecode.model.forms import (
|
||||
UserForm, UserPermissionsForm, UserIndividualPermissionsForm)
|
||||
from rhodecode.model.repo_group import RepoGroupModel
|
||||
from rhodecode.model.user import UserModel
|
||||
from rhodecode.model.meta import Session
|
||||
from rhodecode.model.permission import PermissionModel
|
||||
from rhodecode.lib.utils import action_logger
|
||||
from rhodecode.lib.ext_json import json
|
||||
from rhodecode.lib.utils2 import datetime_to_time, safe_int
|
||||
from rhodecode.lib.utils2 import datetime_to_time, safe_int, AttributeDict
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
|
@ -120,6 +121,16 @@ class UsersController(BaseController):
|
|||
c.data = json.dumps(users_data)
|
||||
return render('admin/users/users.html')
|
||||
|
||||
def _get_personal_repo_group_template_vars(self):
|
||||
DummyUser = AttributeDict({
|
||||
'username': '${username}',
|
||||
'user_id': '${user_id}',
|
||||
})
|
||||
c.default_create_repo_group = RepoGroupModel() \
|
||||
.get_default_create_personal_repo_group()
|
||||
c.personal_repo_group_name = RepoGroupModel() \
|
||||
.get_personal_group_name(DummyUser)
|
||||
|
||||
@HasPermissionAllDecorator('hg.admin')
|
||||
@auth.CSRFRequired()
|
||||
def create(self):
|
||||
|
|
@ -143,6 +154,7 @@ class UsersController(BaseController):
|
|||
% {'user_link': user_link}), category='success')
|
||||
Session().commit()
|
||||
except formencode.Invalid as errors:
|
||||
self._get_personal_repo_group_template_vars()
|
||||
return htmlfill.render(
|
||||
render('admin/users/user_add.html'),
|
||||
defaults=errors.value,
|
||||
|
|
@ -163,6 +175,7 @@ class UsersController(BaseController):
|
|||
"""GET /users/new: Form to create a new item"""
|
||||
# url('new_user')
|
||||
c.default_extern_type = auth_rhodecode.RhodeCodeAuthPlugin.name
|
||||
self._get_personal_repo_group_template_vars()
|
||||
return render('admin/users/user_add.html')
|
||||
|
||||
@HasPermissionAllDecorator('hg.admin')
|
||||
|
|
@ -339,22 +352,41 @@ class UsersController(BaseController):
|
|||
|
||||
user_id = safe_int(user_id)
|
||||
c.user = User.get_or_404(user_id)
|
||||
personal_repo_group = RepoGroup.get_user_personal_repo_group(
|
||||
c.user.user_id)
|
||||
if personal_repo_group:
|
||||
return redirect(url('edit_user_advanced', user_id=user_id))
|
||||
|
||||
personal_repo_group_name = RepoGroupModel().get_personal_group_name(
|
||||
c.user)
|
||||
named_personal_group = RepoGroup.get_by_group_name(
|
||||
personal_repo_group_name)
|
||||
try:
|
||||
desc = RepoGroupModel.PERSONAL_GROUP_DESC % {
|
||||
'username': c.user.username}
|
||||
if not RepoGroup.get_by_group_name(c.user.username):
|
||||
RepoGroupModel().create(group_name=c.user.username,
|
||||
group_description=desc,
|
||||
owner=c.user.username)
|
||||
|
||||
msg = _('Created repository group `%s`' % (c.user.username,))
|
||||
if named_personal_group and named_personal_group.user_id == c.user.user_id:
|
||||
# migrate the same named group, and mark it as personal
|
||||
named_personal_group.personal = True
|
||||
Session().add(named_personal_group)
|
||||
Session().commit()
|
||||
msg = _('Linked repository group `%s` as personal' % (
|
||||
personal_repo_group_name,))
|
||||
h.flash(msg, category='success')
|
||||
elif not named_personal_group:
|
||||
RepoGroupModel().create_personal_repo_group(c.user)
|
||||
|
||||
msg = _('Created repository group `%s`' % (
|
||||
personal_repo_group_name,))
|
||||
h.flash(msg, category='success')
|
||||
else:
|
||||
msg = _('Repository group `%s` is already taken' % (
|
||||
personal_repo_group_name,))
|
||||
h.flash(msg, category='warning')
|
||||
except Exception:
|
||||
log.exception("Exception during repository group creation")
|
||||
msg = _(
|
||||
'An error occurred during repository group creation for user')
|
||||
h.flash(msg, category='error')
|
||||
Session().rollback()
|
||||
|
||||
return redirect(url('edit_user_advanced', user_id=user_id))
|
||||
|
||||
|
|
@ -397,7 +429,9 @@ class UsersController(BaseController):
|
|||
|
||||
c.active = 'advanced'
|
||||
c.perm_user = AuthUser(user_id=user_id, ip_addr=self.ip_addr)
|
||||
c.personal_repo_group = RepoGroup.get_by_group_name(user.username)
|
||||
c.personal_repo_group = c.perm_user.personal_repo_group
|
||||
c.personal_repo_group_name = RepoGroupModel()\
|
||||
.get_personal_group_name(user)
|
||||
c.first_admin = User.get_first_super_admin()
|
||||
defaults = user.get_dict()
|
||||
|
||||
|
|
|
|||
|
|
@ -60,8 +60,7 @@ class ForksController(BaseRepoController):
|
|||
c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
|
||||
choices, c.landing_revs = ScmModel().get_repo_landing_revs()
|
||||
c.landing_revs_choices = choices
|
||||
c.personal_repo_group = RepoGroup.get_by_group_name(
|
||||
c.rhodecode_user.username)
|
||||
c.personal_repo_group = c.rhodecode_user.personal_repo_group
|
||||
|
||||
def __load_data(self, repo_name=None):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ from rhodecode.events.base import RhodecodeEvent
|
|||
|
||||
from rhodecode.events.user import ( # noqa
|
||||
UserPreCreate,
|
||||
UserPostCreate,
|
||||
UserPreUpdate,
|
||||
UserRegistered
|
||||
)
|
||||
|
|
|
|||
|
|
@ -51,6 +51,19 @@ class UserPreCreate(RhodecodeEvent):
|
|||
self.user_data = user_data
|
||||
|
||||
|
||||
@implementer(IUserPreCreate)
|
||||
class UserPostCreate(RhodecodeEvent):
|
||||
"""
|
||||
An instance of this class is emitted as an :term:`event` after a new user
|
||||
object is created.
|
||||
"""
|
||||
name = 'user-post-create'
|
||||
display_name = lazy_ugettext('user post create')
|
||||
|
||||
def __init__(self, user_data):
|
||||
self.user_data = user_data
|
||||
|
||||
|
||||
@implementer(IUserPreUpdate)
|
||||
class UserPreUpdate(RhodecodeEvent):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ from rhodecode.model.meta import Session
|
|||
from rhodecode.model.user import UserModel
|
||||
from rhodecode.model.db import (
|
||||
User, Repository, Permission, UserToPerm, UserGroupToPerm, UserGroupMember,
|
||||
UserIpMap, UserApiKeys)
|
||||
UserIpMap, UserApiKeys, RepoGroup)
|
||||
from rhodecode.lib import caches
|
||||
from rhodecode.lib.utils2 import safe_unicode, aslist, safe_str, md5
|
||||
from rhodecode.lib.utils import (
|
||||
|
|
@ -983,6 +983,9 @@ class AuthUser(object):
|
|||
inherit = self.inherit_default_permissions
|
||||
return AuthUser.check_ip_allowed(self.user_id, self.ip_addr,
|
||||
inherit_from_default=inherit)
|
||||
@property
|
||||
def personal_repo_group(self):
|
||||
return RepoGroup.get_user_personal_repo_group(self.user_id)
|
||||
|
||||
@classmethod
|
||||
def check_ip_allowed(cls, user_id, ip_addr, inherit_from_default):
|
||||
|
|
|
|||
27
rhodecode/lib/dbmigrate/versions/063_version_4_5_0.py
Normal file
27
rhodecode/lib/dbmigrate/versions/063_version_4_5_0.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import logging
|
||||
|
||||
from sqlalchemy import Column, MetaData, Boolean
|
||||
|
||||
from rhodecode.lib.dbmigrate.versions import _reset_base
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
"""
|
||||
Upgrade operations go here.
|
||||
Don't create your own engine; bind migrate_engine to your metadata
|
||||
"""
|
||||
_reset_base(migrate_engine)
|
||||
from rhodecode.lib.dbmigrate.schema import db_4_5_0_0 as db
|
||||
|
||||
# Add personal column to RepoGroup table.
|
||||
rg_table = db.RepoGroup.__table__
|
||||
rg_col = Column(
|
||||
'personal', Boolean(), nullable=True, unique=None, default=None)
|
||||
rg_col.create(table=rg_table)
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta = MetaData()
|
||||
meta.bind = migrate_engine
|
||||
|
|
@ -96,7 +96,7 @@ def __get_lem(extra_mapping=None):
|
|||
|
||||
def str2bool(_str):
|
||||
"""
|
||||
returs True/False value from given string, it tries to translate the
|
||||
returns True/False value from given string, it tries to translate the
|
||||
string into boolean
|
||||
|
||||
:param _str: string value to translate into boolean
|
||||
|
|
|
|||
|
|
@ -2028,6 +2028,7 @@ class RepoGroup(Base, BaseModel):
|
|||
enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
|
||||
user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=False, default=None)
|
||||
created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
|
||||
personal = Column('personal', Boolean(), nullable=True, unique=None, default=None)
|
||||
|
||||
repo_group_to_perm = relationship('UserRepoGroupToPerm', cascade='all', order_by='UserRepoGroupToPerm.group_to_perm_id')
|
||||
users_group_to_perm = relationship('UserGroupRepoGroupToPerm', cascade='all')
|
||||
|
|
@ -2082,6 +2083,13 @@ class RepoGroup(Base, BaseModel):
|
|||
"get_group_%s" % _hash_key(group_name)))
|
||||
return gr.scalar()
|
||||
|
||||
@classmethod
|
||||
def get_user_personal_repo_group(cls, user_id):
|
||||
user = User.get(user_id)
|
||||
return cls.query()\
|
||||
.filter(cls.personal == true())\
|
||||
.filter(cls.user == user).scalar()
|
||||
|
||||
@classmethod
|
||||
def get_all_repo_groups(cls, user_id=Optional(None), group_id=Optional(None),
|
||||
case_insensitive=True):
|
||||
|
|
|
|||
|
|
@ -341,6 +341,8 @@ def ApplicationSettingsForm():
|
|||
rhodecode_post_code = v.UnicodeString(strip=True, min=1, not_empty=False)
|
||||
rhodecode_captcha_public_key = v.UnicodeString(strip=True, min=1, not_empty=False)
|
||||
rhodecode_captcha_private_key = v.UnicodeString(strip=True, min=1, not_empty=False)
|
||||
rhodecode_create_personal_repo_group = v.StringBoolean(if_missing=False)
|
||||
rhodecode_personal_repo_group_pattern = v.UnicodeString(strip=True, min=1, not_empty=False)
|
||||
|
||||
return _ApplicationSettingsForm
|
||||
|
||||
|
|
|
|||
|
|
@ -23,13 +23,13 @@
|
|||
repo group model for RhodeCode
|
||||
"""
|
||||
|
||||
|
||||
import os
|
||||
import datetime
|
||||
import itertools
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import traceback
|
||||
import string
|
||||
|
||||
from zope.cachedescriptors.property import Lazy as LazyProperty
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ from rhodecode.model import BaseModel
|
|||
from rhodecode.model.db import (
|
||||
RepoGroup, UserRepoGroupToPerm, User, Permission, UserGroupRepoGroupToPerm,
|
||||
UserGroup, Repository)
|
||||
from rhodecode.model.settings import VcsSettingsModel
|
||||
from rhodecode.model.settings import VcsSettingsModel, SettingsModel
|
||||
from rhodecode.lib.caching_query import FromCache
|
||||
from rhodecode.lib.utils2 import action_logger_generic
|
||||
|
||||
|
|
@ -49,6 +49,7 @@ class RepoGroupModel(BaseModel):
|
|||
|
||||
cls = RepoGroup
|
||||
PERSONAL_GROUP_DESC = '[personal] repo group: owner `%(username)s`'
|
||||
PERSONAL_GROUP_PATTERN = '${username}' # default
|
||||
|
||||
def _get_user_group(self, users_group):
|
||||
return self._get_instance(UserGroup, users_group,
|
||||
|
|
@ -76,6 +77,39 @@ class RepoGroupModel(BaseModel):
|
|||
"sql_cache_short", "get_repo_group_%s" % repo_group_name))
|
||||
return repo.scalar()
|
||||
|
||||
def get_default_create_personal_repo_group(self):
|
||||
value = SettingsModel().get_setting_by_name(
|
||||
'create_personal_repo_group')
|
||||
return value.app_settings_value if value else None or False
|
||||
|
||||
def get_personal_group_name_pattern(self):
|
||||
value = SettingsModel().get_setting_by_name(
|
||||
'personal_repo_group_pattern')
|
||||
val = value.app_settings_value if value else None
|
||||
group_template = val or self.PERSONAL_GROUP_PATTERN
|
||||
|
||||
group_template = group_template.lstrip('/')
|
||||
return group_template
|
||||
|
||||
def get_personal_group_name(self, user):
|
||||
template = self.get_personal_group_name_pattern()
|
||||
return string.Template(template).safe_substitute(
|
||||
username=user.username,
|
||||
user_id=user.user_id,
|
||||
)
|
||||
|
||||
def create_personal_repo_group(self, user, commit_early=True):
|
||||
desc = self.PERSONAL_GROUP_DESC % {'username': user.username}
|
||||
personal_repo_group_name = self.get_personal_group_name(user)
|
||||
|
||||
# create a new one
|
||||
RepoGroupModel().create(
|
||||
group_name=personal_repo_group_name,
|
||||
group_description=desc,
|
||||
owner=user.username,
|
||||
personal=True,
|
||||
commit_early=commit_early)
|
||||
|
||||
def _create_default_perms(self, new_group):
|
||||
# create default permission
|
||||
default_perm = 'group.read'
|
||||
|
|
@ -191,7 +225,7 @@ class RepoGroupModel(BaseModel):
|
|||
shutil.move(rm_path, os.path.join(self.repos_path, _d))
|
||||
|
||||
def create(self, group_name, group_description, owner, just_db=False,
|
||||
copy_permissions=False, commit_early=True):
|
||||
copy_permissions=False, personal=None, commit_early=True):
|
||||
|
||||
(group_name_cleaned,
|
||||
parent_group_name) = RepoGroupModel()._get_group_name_and_parent(group_name)
|
||||
|
|
@ -199,11 +233,18 @@ class RepoGroupModel(BaseModel):
|
|||
parent_group = None
|
||||
if parent_group_name:
|
||||
parent_group = self._get_repo_group(parent_group_name)
|
||||
if not parent_group:
|
||||
# we tried to create a nested group, but the parent is not
|
||||
# existing
|
||||
raise ValueError(
|
||||
'Parent group `%s` given in `%s` group name '
|
||||
'is not yet existing.' % (parent_group_name, group_name))
|
||||
|
||||
# becase we are doing a cleanup, we need to check if such directory
|
||||
# already exists. If we don't do that we can accidentally delete existing
|
||||
# directory via cleanup that can cause data issues, since delete does a
|
||||
# folder rename to special syntax later cleanup functions can delete this
|
||||
# because we are doing a cleanup, we need to check if such directory
|
||||
# already exists. If we don't do that we can accidentally delete
|
||||
# existing directory via cleanup that can cause data issues, since
|
||||
# delete does a folder rename to special syntax later cleanup
|
||||
# functions can delete this
|
||||
cleanup_group = self.check_exist_filesystem(group_name,
|
||||
exc_on_failure=False)
|
||||
try:
|
||||
|
|
@ -213,6 +254,7 @@ class RepoGroupModel(BaseModel):
|
|||
new_repo_group.group_description = group_description or group_name
|
||||
new_repo_group.parent_group = parent_group
|
||||
new_repo_group.group_name = group_name
|
||||
new_repo_group.personal = personal
|
||||
|
||||
self.sa.add(new_repo_group)
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ from sqlalchemy.sql.expression import true, false
|
|||
from rhodecode import events
|
||||
from rhodecode.lib.utils2 import (
|
||||
safe_unicode, get_current_rhodecode_user, action_logger_generic,
|
||||
AttributeDict)
|
||||
AttributeDict, str2bool)
|
||||
from rhodecode.lib.caching_query import FromCache
|
||||
from rhodecode.model import BaseModel
|
||||
from rhodecode.model.auth_token import AuthTokenModel
|
||||
|
|
@ -104,12 +104,13 @@ class UserModel(BaseModel):
|
|||
'cur_user': cur_user
|
||||
}
|
||||
|
||||
if 'create_repo_group' in form_data:
|
||||
user_data['create_repo_group'] = str2bool(
|
||||
form_data.get('create_repo_group'))
|
||||
|
||||
try:
|
||||
if form_data.get('create_repo_group'):
|
||||
user_data['create_repo_group'] = True
|
||||
if form_data.get('password_change'):
|
||||
user_data['force_password_change'] = True
|
||||
|
||||
return UserModel().create_or_update(**user_data)
|
||||
except Exception:
|
||||
log.error(traceback.format_exc())
|
||||
|
|
@ -177,7 +178,7 @@ class UserModel(BaseModel):
|
|||
self, username, password, email, firstname='', lastname='',
|
||||
active=True, admin=False, extern_type=None, extern_name=None,
|
||||
cur_user=None, plugin=None, force_password_change=False,
|
||||
allow_to_create_user=True, create_repo_group=False,
|
||||
allow_to_create_user=True, create_repo_group=None,
|
||||
updating_user_id=None, language=None, strict_creation_check=True):
|
||||
"""
|
||||
Creates a new instance if not found, or updates current one
|
||||
|
|
@ -222,8 +223,8 @@ class UserModel(BaseModel):
|
|||
# in case it's a plugin we don't care
|
||||
if not plugin:
|
||||
|
||||
# first check if we gave crypted password back, and if it matches
|
||||
# it's not password change
|
||||
# first check if we gave crypted password back, and if it
|
||||
# matches it's not password change
|
||||
if new_user.password == password:
|
||||
return False
|
||||
|
||||
|
|
@ -233,6 +234,12 @@ class UserModel(BaseModel):
|
|||
|
||||
return False
|
||||
|
||||
# read settings on default personal repo group creation
|
||||
if create_repo_group is None:
|
||||
default_create_repo_group = RepoGroupModel()\
|
||||
.get_default_create_personal_repo_group()
|
||||
create_repo_group = default_create_repo_group
|
||||
|
||||
user_data = {
|
||||
'username': username,
|
||||
'password': password,
|
||||
|
|
@ -319,17 +326,16 @@ class UserModel(BaseModel):
|
|||
self.sa.add(new_user)
|
||||
|
||||
if not edit and create_repo_group:
|
||||
# create new group same as username, and make this user an owner
|
||||
desc = RepoGroupModel.PERSONAL_GROUP_DESC % {'username': username}
|
||||
RepoGroupModel().create(group_name=username,
|
||||
group_description=desc,
|
||||
owner=username, commit_early=False)
|
||||
RepoGroupModel().create_personal_repo_group(
|
||||
new_user, commit_early=False)
|
||||
|
||||
if not edit:
|
||||
# add the RSS token
|
||||
AuthTokenModel().create(username,
|
||||
description='Generated feed token',
|
||||
role=AuthTokenModel.cls.ROLE_FEED)
|
||||
log_create_user(created_by=cur_user, **new_user.get_dict())
|
||||
events.trigger(events.UserPostCreate(user_data))
|
||||
return new_user
|
||||
except (DatabaseError,):
|
||||
log.error(traceback.format_exc())
|
||||
|
|
|
|||
|
|
@ -30,6 +30,35 @@ ${h.secure_form(url('admin_settings_global'), method='post')}
|
|||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading" id="personal-group-options">
|
||||
<h3 class="panel-title">${_('Personal Repository Group')} <a class="permalink" href="#personal-group-options"> ¶</a></h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="checkbox">
|
||||
${h.checkbox('rhodecode_create_personal_repo_group','True')}
|
||||
<label for="rhodecode_create_personal_repo_group">${_('Create Personal Repository Group')}</label>
|
||||
</div>
|
||||
<span class="help-block">
|
||||
${_('Always create Personal Repository Groups for new users.')} <br/>
|
||||
${_('When creating new users from add user form or API you can still turn this off via a checkbox or flag')}
|
||||
</span>
|
||||
|
||||
<div class="label">
|
||||
<label for="rhodecode_personal_repo_group_pattern">${_('Personal Repo Group Pattern')}</label>
|
||||
</div>
|
||||
<div class="field input">
|
||||
${h.text('rhodecode_personal_repo_group_pattern',size=60, placeholder=c.personal_repo_group_default_pattern)}
|
||||
</div>
|
||||
<span class="help-block">
|
||||
${_('Pattern used to create Personal Repository Groups. Prefix can be other existing repository group path[s], eg. /u/${username}')} <br/>
|
||||
${_('Available variables are currently ${username} and ${user_id}')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading" id="captcha-options">
|
||||
<h3 class="panel-title">${_('Registration Captcha')} <a class="permalink" href="#captcha-options"> ¶</a></h3>
|
||||
|
|
|
|||
|
|
@ -113,11 +113,14 @@
|
|||
|
||||
<div class="field">
|
||||
<div class="label label-checkbox">
|
||||
<label for="create_repo_group">${_('Add repository group')}:</label>
|
||||
<label for="create_repo_group">${_('Add personal repository group')}:</label>
|
||||
</div>
|
||||
<div class="checkboxes">
|
||||
${h.checkbox('create_repo_group',value=True)}
|
||||
<span class="help-block">${_('Add repository group with the same name as username. \nUser will be automatically set as this group owner.')}</span>
|
||||
${h.checkbox('create_repo_group',value=True, checked=c.default_create_repo_group)}
|
||||
<span class="help-block">
|
||||
${_('New group will be created at: `/%(path)s`') % {'path': c.personal_repo_group_name}}<br/>
|
||||
${_('User will be automatically set as this group owner.')}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -61,7 +61,11 @@
|
|||
%if c.personal_repo_group:
|
||||
<div class="panel-body-title-text">${_('Users personal repository group')} : ${h.link_to(c.personal_repo_group.group_name, url('repo_group_home', group_name=c.personal_repo_group.group_name))}</div>
|
||||
%else:
|
||||
<div class="panel-body-title-text">${_('This user currently does not have a personal repository group')}</div>
|
||||
<div class="panel-body-title-text">
|
||||
${_('This user currently does not have a personal repository group')}
|
||||
<br/>
|
||||
${_('New group will be created at: `/%(path)s`') % {'path': c.personal_repo_group_name}}
|
||||
</div>
|
||||
%endif
|
||||
<button class="btn btn-default" type="submit" ${'disabled="disabled"' if c.personal_repo_group else ''}>
|
||||
<i class="icon-folder-close"></i>
|
||||
|
|
|
|||
|
|
@ -338,6 +338,9 @@
|
|||
<div class="">
|
||||
<ol class="links">
|
||||
<li>${h.link_to(_(u'My account'),h.url('my_account'))}</li>
|
||||
% if c.rhodecode_user.personal_repo_group:
|
||||
<li>${h.link_to(_(u'My personal group'), h.url('repo_group_home', group_name=c.rhodecode_user.personal_repo_group.group_name))}</li>
|
||||
% endif
|
||||
<li class="logout">
|
||||
${h.secure_form(h.route_path('logout'))}
|
||||
${h.submit('log_out', _(u'Sign Out'),class_="btn btn-primary")}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue