Пример #1
0
def get_gists(request, apiuser, userid=Optional(OAttr('apiuser'))):
    """
    Get all gists for given user. If userid is empty returned gists
    are for user who called the api

    :param apiuser: This is filled automatically from the |authtoken|.
    :type apiuser: AuthUser
    :param userid: user to get gists for
    :type userid: Optional(str or int)
    """

    if not has_superadmin_permission(apiuser):
        # make sure normal user does not pass someone else userid,
        # he is not allowed to do that
        if not isinstance(userid, Optional) and userid != apiuser.user_id:
            raise JSONRPCError(
                'userid is not the same as your user'
            )

    if isinstance(userid, Optional):
        user_id = apiuser.user_id
    else:
        user_id = get_user_or_error(userid).user_id

    gists = []
    _gists = Gist().query() \
        .filter(or_(
        Gist.gist_expires == -1, Gist.gist_expires >= time.time())) \
        .filter(Gist.gist_owner == user_id) \
        .order_by(Gist.created_on.desc())
    for gist in _gists:
        gists.append(gist.get_api_data())
    return gists
def close_pull_request(request,
                       apiuser,
                       repoid,
                       pullrequestid,
                       userid=Optional(OAttr('apiuser'))):
    """
    Close the pull request specified by `pullrequestid`.

    :param apiuser: This is filled automatically from the |authtoken|.
    :type apiuser: AuthUser
    :param repoid: Repository name or repository ID to which the pull
        request belongs.
    :type repoid: str or int
    :param pullrequestid: ID of the pull request to be closed.
    :type pullrequestid: int
    :param userid: Close the pull request as this user.
    :type userid: Optional(str or int)

    Example output:

    .. code-block:: bash

      "id": <id_given_in_input>,
      "result":
        {
            "pull_request_id":  "<int>",
            "closed":           "<bool>"
        },
      "error": null

    """
    repo = get_repo_or_error(repoid)
    if not isinstance(userid, Optional):
        if (has_superadmin_permission(apiuser)
                or HasRepoPermissionAnyApi('repository.admin')(
                    user=apiuser, repo_name=repo.repo_name)):
            apiuser = get_user_or_error(userid)
        else:
            raise JSONRPCError('userid is not the same as your user')

    pull_request = get_pull_request_or_error(pullrequestid)
    if not PullRequestModel().check_user_update(
            pull_request, apiuser, api=True):
        raise JSONRPCError(
            'pull request `%s` close failed, no permission to close.' %
            (pullrequestid, ))
    if pull_request.is_closed():
        raise JSONRPCError('pull request `%s` is already closed' %
                           (pullrequestid, ))

    PullRequestModel().close_pull_request(pull_request.pull_request_id,
                                          apiuser)
    Session.commit()
    data = {
        'pull_request_id': pull_request.pull_request_id,
        'closed': True,
    }
    return data
Пример #3
0
def changeset_comment(request,
                      apiuser,
                      repoid,
                      revision,
                      message,
                      userid=Optional(OAttr('apiuser')),
                      status=Optional(None)):
    """
    Set a changeset comment, and optionally change the status of the
    changeset.

    This command can only be run using an |authtoken| with admin
    permissions on the |repo|.

    :param apiuser: This is filled automatically from the |authtoken|.
    :type apiuser: AuthUser
    :param repoid: Set the repository name or repository ID.
    :type repoid: str or int
    :param revision: Specify the revision for which to set a comment.
    :type revision: str
    :param message: The comment text.
    :type message: str
    :param userid: Set the user name of the comment creator.
    :type userid: Optional(str or int)
    :param status: Set the comment status. The following are valid options:
        * not_reviewed
        * approved
        * rejected
        * under_review
    :type status: str

    Example error output:

    .. code-block:: json

        {
            "id" : <id_given_in_input>,
            "result" : {
                "msg": "Commented on commit `<revision>` for repository `<repoid>`",
                "status_change": null or <status>,
                "success": true
            },
            "error" : null
        }

    """
    from .repo_api import comment_commit

    return comment_commit(request=request,
                          apiuser=apiuser,
                          repoid=repoid,
                          commit_id=revision,
                          message=message,
                          userid=userid,
                          status=status)
Пример #4
0
def test_params_opt(request,
                    apiuser,
                    params,
                    opt1=False,
                    opt2=Optional(True),
                    opt3=Optional(OAttr('apiuser'))):
    opt2 = Optional.extract(opt2)
    opt3 = Optional.extract(opt3, evaluate_locals=locals())

    return u'hello apiuser:{} params:{}, opt:[{},{},{}]'.format(
        apiuser, params, opt1, opt2, opt3)
Пример #5
0
def update_repo_group(
        request, apiuser, repogroupid, group_name=Optional(''),
        description=Optional(''), owner=Optional(OAttr('apiuser')),
        parent=Optional(None), enable_locking=Optional(False)):
    """
    Updates repository group with the details given.

    This command can only be run using an |authtoken| with admin
    permissions.

    :param apiuser: This is filled automatically from the |authtoken|.
    :type apiuser: AuthUser
    :param repogroupid: Set the ID of repository group.
    :type repogroupid: str or int
    :param group_name: Set the name of the |repo| group.
    :type group_name: str
    :param description: Set a description for the group.
    :type description: str
    :param owner: Set the |repo| group owner.
    :type owner: str
    :param parent: Set the |repo| group parent.
    :type parent: str or int
    :param enable_locking: Enable |repo| locking. The default is false.
    :type enable_locking: bool
    """

    repo_group = get_repo_group_or_error(repogroupid)
    if not has_superadmin_permission(apiuser):
        # check if we have admin permission for this repo group !
        _perms = ('group.admin',)
        if not HasRepoGroupPermissionAnyApi(*_perms)(
                user=apiuser, group_name=repo_group.group_name):
            raise JSONRPCError(
                'repository group `%s` does not exist' % (repogroupid,))

    updates = {}
    try:
        store_update(updates, group_name, 'group_name')
        store_update(updates, description, 'group_description')
        store_update(updates, owner, 'user')
        store_update(updates, parent, 'group_parent_id')
        store_update(updates, enable_locking, 'enable_locking')
        repo_group = RepoGroupModel().update(repo_group, updates)
        Session().commit()
        return {
            'msg': 'updated repository group ID:%s %s' % (
                repo_group.group_id, repo_group.group_name),
            'repo_group': repo_group.get_api_data()
        }
    except Exception:
        log.exception("Exception occurred while trying update repo group")
        raise JSONRPCError('failed to update repository group `%s`'
                           % (repogroupid,))
Пример #6
0
def get_user_locks(request, apiuser, userid=Optional(OAttr('apiuser'))):
    """
    Displays all repositories locked by the specified user.

    * If this command is run by a non-admin user, it returns
      a list of |repos| locked by that user.

    This command takes the following options:

    :param apiuser: This is filled automatically from the |authtoken|.
    :type apiuser: AuthUser
    :param userid: Sets the userid whose list of locked |repos| will be
        displayed.
    :type userid: Optional(str or int)

    Example output:

    .. code-block:: bash

        id : <id_given_in_input>
        result : {
            [repo_object, repo_object,...]
        }
        error :  null
    """

    include_secrets = False
    if not has_superadmin_permission(apiuser):
        # make sure normal user does not pass someone else userid,
        # he is not allowed to do that
        if not isinstance(userid, Optional) and userid != apiuser.user_id:
            raise JSONRPCError('userid is not the same as your user')
    else:
        include_secrets = True

    userid = Optional.extract(userid, evaluate_locals=locals())
    userid = getattr(userid, 'user_id', userid)
    user = get_user_or_error(userid)

    ret = []

    # show all locks
    for r in Repository.getAll():
        _user_id, _time, _reason = r.locked
        if _user_id and _time:
            _api_data = r.get_api_data(include_secrets=include_secrets)
            # if we use user filter just show the locks for this user
            if safe_int(_user_id) == user.user_id:
                ret.append(_api_data)

    return ret
Пример #7
0
def get_ip(request, apiuser, userid=Optional(OAttr('apiuser'))):
    """
    Displays the IP Address as seen from the |RCE| server.

    * This command displays the IP Address, as well as all the defined IP
      addresses for the specified user. If the ``userid`` is not set, the
      data returned is for the user calling the method.

    This command can only be run using an |authtoken| with admin rights to
    the specified repository.

    This command takes the following options:

    :param apiuser: This is filled automatically from |authtoken|.
    :type apiuser: AuthUser
    :param userid: Sets the userid for which associated IP Address data
        is returned.
    :type userid: Optional(str or int)

    Example output:

    .. code-block:: bash

        id : <id_given_in_input>
        result : {
                     "server_ip_addr": "<ip_from_clien>",
                     "user_ips": [
                                    {
                                       "ip_addr": "<ip_with_mask>",
                                       "ip_range": ["<start_ip>", "<end_ip>"],
                                    },
                                    ...
                                 ]
        }

    """
    if not has_superadmin_permission(apiuser):
        raise JSONRPCForbidden()

    userid = Optional.extract(userid, evaluate_locals=locals())
    userid = getattr(userid, 'user_id', userid)

    user = get_user_or_error(userid)
    ips = UserIpMap.query().filter(UserIpMap.user == user).all()
    return {
        'server_ip_addr': request.rpc_ip_addr,
        'user_ips': ips
    }
Пример #8
0
def get_user(request, apiuser, userid=Optional(OAttr('apiuser'))):
    """
    Returns the information associated with a username or userid.

    * If the ``userid`` is not set, this command returns the information
      for the ``userid`` calling the method.

    .. note::

       Normal users may only run this command against their ``userid``. For
       full privileges you must run this command using an |authtoken| with
       admin rights.

    :param apiuser: This is filled automatically from the |authtoken|.
    :type apiuser: AuthUser
    :param userid: Sets the userid for which data will be returned.
    :type userid: Optional(str or int)

    Example output:

    .. code-block:: bash

        {
          "error": null,
          "id": <id>,
          "result": {
            "active": true,
            "admin": false,
            "api_key": "api-key",
            "api_keys": [ list of keys ],
            "email": "*****@*****.**",
            "emails": [
              "*****@*****.**"
            ],
            "extern_name": "rhodecode",
            "extern_type": "rhodecode",
            "firstname": "username",
            "ip_addresses": [],
            "language": null,
            "last_login": "******",
            "lastname": "surnae",
            "permissions": {
              "global": [
                "hg.inherit_default_perms.true",
                "usergroup.read",
                "hg.repogroup.create.false",
                "hg.create.none",
                "hg.extern_activate.manual",
                "hg.create.write_on_repogroup.false",
                "hg.usergroup.create.false",
                "group.none",
                "repository.none",
                "hg.register.none",
                "hg.fork.repository"
              ],
              "repositories": { "username/example": "repository.write"},
              "repositories_groups": { "user-group/repo": "group.none" },
              "user_groups": { "user_group_name": "usergroup.read" }
            },
            "user_id": 32,
            "username": "******"
          }
        }
    """

    if not has_superadmin_permission(apiuser):
        # make sure normal user does not pass someone else userid,
        # he is not allowed to do that
        if not isinstance(userid, Optional) and userid != apiuser.user_id:
            raise JSONRPCError('userid is not the same as your user')

    userid = Optional.extract(userid, evaluate_locals=locals())
    userid = getattr(userid, 'user_id', userid)

    user = get_user_or_error(userid)
    data = user.get_api_data(include_secrets=True)
    data['permissions'] = AuthUser(user_id=user.user_id).permissions
    return data
Пример #9
0
def create_gist(
        request, apiuser, files, owner=Optional(OAttr('apiuser')),
        gist_type=Optional(Gist.GIST_PUBLIC), lifetime=Optional(-1),
        acl_level=Optional(Gist.ACL_LEVEL_PUBLIC),
        description=Optional('')):
    """
    Creates a new Gist.

    :param apiuser: This is filled automatically from the |authtoken|.
    :type apiuser: AuthUser
    :param files: files to be added to the gist. The data structure has
        to match the following example::

          {'filename': {'content':'...', 'lexer': null},
           'filename2': {'content':'...', 'lexer': null}}

    :type files: dict
    :param owner: Set the gist owner, defaults to api method caller
    :type owner: Optional(str or int)
    :param gist_type: type of gist ``public`` or ``private``
    :type gist_type: Optional(str)
    :param lifetime: time in minutes of gist lifetime
    :type lifetime: Optional(int)
    :param acl_level: acl level for this gist, can be
        ``acl_public`` or ``acl_private`` If the value is set to
        ``acl_private`` only logged in users are able to access this gist.
        If not set it defaults to ``acl_public``.
    :type acl_level: Optional(str)
    :param description: gist description
    :type description: Optional(str)

    Example  output:

    .. code-block:: bash

      id : <id_given_in_input>
      result : {
        "msg": "created new gist",
        "gist": {}
      }
      error :  null

    Example error output:

    .. code-block:: bash

      id : <id_given_in_input>
      result : null
      error :  {
        "failed to create gist"
      }

    """

    try:
        if isinstance(owner, Optional):
            owner = apiuser.user_id

        owner = get_user_or_error(owner)
        description = Optional.extract(description)
        gist_type = Optional.extract(gist_type)
        lifetime = Optional.extract(lifetime)
        acl_level = Optional.extract(acl_level)

        gist = GistModel().create(description=description,
                                  owner=owner,
                                  gist_mapping=files,
                                  gist_type=gist_type,
                                  lifetime=lifetime,
                                  gist_acl_level=acl_level)
        Session().commit()
        return {
            'msg': 'created new gist',
            'gist': gist.get_api_data()
        }
    except Exception:
        log.exception('Error occurred during creation of gist')
        raise JSONRPCError('failed to create gist')
Пример #10
0
def show_ip(request, apiuser, userid=Optional(OAttr('apiuser'))):
    from .server_api import get_ip
    return get_ip(request=request, apiuser=apiuser, userid=userid)
Пример #11
0
def create_repo_group(request, apiuser, group_name, description=Optional(''),
                      owner=Optional(OAttr('apiuser')),
                      copy_permissions=Optional(False)):
    """
    Creates a repository group.

    * If the repository group name contains "/", all the required repository
      groups will be created.

      For example "foo/bar/baz" will create |repo| groups "foo" and "bar"
      (with "foo" as parent). It will also create the "baz" repository
      with "bar" as |repo| group.

    This command can only be run using an |authtoken| with admin
    permissions.

    :param apiuser: This is filled automatically from the |authtoken|.
    :type apiuser: AuthUser
    :param group_name: Set the repository group name.
    :type group_name: str
    :param description: Set the |repo| group description.
    :type description: str
    :param owner: Set the |repo| group owner.
    :type owner: str
    :param copy_permissions:
    :type copy_permissions:

    Example output:

    .. code-block:: bash

      id : <id_given_in_input>
      result : {
          "msg": "Created new repo group `<repo_group_name>`"
          "repo_group": <repogroup_object>
      }
      error :  null


    Example error output:

    .. code-block:: bash

      id : <id_given_in_input>
      result : null
      error :  {
        failed to create repo group `<repogroupid>`
      }

    """

    schema = RepoGroupSchema()
    try:
        data = schema.deserialize({
            'group_name': group_name
        })
    except colander.Invalid as e:
        raise JSONRPCError("Validation failed: %s" % (e.asdict(),))
    group_name = data['group_name']

    if isinstance(owner, Optional):
        owner = apiuser.user_id

    group_description = Optional.extract(description)
    copy_permissions = Optional.extract(copy_permissions)

    # get by full name with parents, check if it already exist
    if RepoGroup.get_by_group_name(group_name):
        raise JSONRPCError("repo group `%s` already exist" % (group_name,))

    (group_name_cleaned,
     parent_group_name) = RepoGroupModel()._get_group_name_and_parent(
        group_name)

    parent_group = None
    if parent_group_name:
        parent_group = get_repo_group_or_error(parent_group_name)

    if not HasPermissionAnyApi(
            'hg.admin', 'hg.repogroup.create.true')(user=apiuser):
        # check if we have admin permission for this parent repo group !
        # users without admin or hg.repogroup.create can only create other
        # groups in groups they own so this is a required, but can be empty
        parent_group = getattr(parent_group, 'group_name', '')
        _perms = ('group.admin',)
        if not HasRepoGroupPermissionAnyApi(*_perms)(
                user=apiuser, group_name=parent_group):
            raise JSONRPCForbidden()

    try:
        repo_group = RepoGroupModel().create(
            group_name=group_name,
            group_description=group_description,
            owner=owner,
            copy_permissions=copy_permissions)
        Session().commit()
        return {
            'msg': 'Created new repo group `%s`' % group_name,
            'repo_group': repo_group.get_api_data()
        }
    except Exception:
        log.exception("Exception occurred while trying create repo group")
        raise JSONRPCError(
            'failed to create repo group `%s`' % (group_name,))
Пример #12
0
 def test_OAttr_object(self):
     oattr1 = OAttr('apiuser')
     assert '<OptionalAttr:apiuser>' == repr(oattr1)
     assert oattr1() == oattr1
Пример #13
0
 def test_Optional_OAttr(self):
     option1 = Optional(OAttr('apiuser'))
     assert 'apiuser' == Optional.extract(option1)
def comment_pull_request(request,
                         apiuser,
                         repoid,
                         pullrequestid,
                         message=Optional(None),
                         status=Optional(None),
                         userid=Optional(OAttr('apiuser'))):
    """
    Comment on the pull request specified with the `pullrequestid`,
    in the |repo| specified by the `repoid`, and optionally change the
    review status.

    :param apiuser: This is filled automatically from the |authtoken|.
    :type apiuser: AuthUser
    :param repoid: The repository name or repository ID.
    :type repoid: str or int
    :param pullrequestid: The pull request ID.
    :type pullrequestid: int
    :param message: The text content of the comment.
    :type message: str
    :param status: (**Optional**) Set the approval status of the pull
        request. Valid options are:
        * not_reviewed
        * approved
        * rejected
        * under_review
    :type status: str
    :param userid: Comment on the pull request as this user
    :type userid: Optional(str or int)

    Example output:

    .. code-block:: bash

      id : <id_given_in_input>
      result :
        {
            "pull_request_id":  "<Integer>",
            "comment_id":       "<Integer>"
        }
      error :  null
    """
    repo = get_repo_or_error(repoid)
    if not isinstance(userid, Optional):
        if (has_superadmin_permission(apiuser)
                or HasRepoPermissionAnyApi('repository.admin')(
                    user=apiuser, repo_name=repo.repo_name)):
            apiuser = get_user_or_error(userid)
        else:
            raise JSONRPCError('userid is not the same as your user')

    pull_request = get_pull_request_or_error(pullrequestid)
    if not PullRequestModel().check_user_read(pull_request, apiuser, api=True):
        raise JSONRPCError('repository `%s` does not exist' % (repoid, ))
    message = Optional.extract(message)
    status = Optional.extract(status)
    if not message and not status:
        raise JSONRPCError('message and status parameter missing')

    if (status not in (st[0] for st in ChangesetStatus.STATUSES)
            and status is not None):
        raise JSONRPCError('unknown comment status`%s`' % status)

    allowed_to_change_status = PullRequestModel().check_user_change_status(
        pull_request, apiuser)
    text = message
    if status and allowed_to_change_status:
        st_message = (('Status change %(transition_icon)s %(status)s') % {
            'transition_icon': '>',
            'status': ChangesetStatus.get_status_lbl(status)
        })
        text = message or st_message

    rc_config = SettingsModel().get_all_settings()
    renderer = rc_config.get('rhodecode_markup_renderer', 'rst')
    comment = ChangesetCommentsModel().create(
        text=text,
        repo=pull_request.target_repo.repo_id,
        user=apiuser.user_id,
        pull_request=pull_request.pull_request_id,
        f_path=None,
        line_no=None,
        status_change=(ChangesetStatus.get_status_lbl(status)
                       if status and allowed_to_change_status else None),
        closing_pr=False,
        renderer=renderer)

    if allowed_to_change_status and status:
        ChangesetStatusModel().set_status(
            pull_request.target_repo.repo_id,
            status,
            apiuser.user_id,
            comment,
            pull_request=pull_request.pull_request_id)
        Session().flush()

    Session().commit()
    data = {
        'pull_request_id': pull_request.pull_request_id,
        'comment_id': comment.comment_id,
        'status': status
    }
    return data
def create_user_group(
        request, apiuser, group_name, description=Optional(''),
        owner=Optional(OAttr('apiuser')), active=Optional(True)):
    """
    Creates a new user group.

    This command can only be run using an |authtoken| with admin rights to
    the specified repository.

    This command takes the following options:

    :param apiuser: This is filled automatically from the |authtoken|.
    :type apiuser: AuthUser
    :param group_name: Set the name of the new user group.
    :type group_name: str
    :param description: Give a description of the new user group.
    :type description: str
    :param owner: Set the owner of the new user group.
        If not set, the owner is the |authtoken| user.
    :type owner: Optional(str or int)
    :param active: Set this group as active.
    :type active: Optional(``True`` | ``False``)

    Example output:

    .. code-block:: bash

        id : <id_given_in_input>
        result: {
                  "msg": "created new user group `<groupname>`",
                  "user_group": <user_group_object>
                }
        error:  null

    Example error output:

    .. code-block:: bash

      id : <id_given_in_input>
      result : null
      error :  {
        "user group `<group name>` already exist"
        or
        "failed to create group `<group name>`"
      }

    """

    if not has_superadmin_permission(apiuser):
        if not HasPermissionAnyApi('hg.usergroup.create.true')(user=apiuser):
            raise JSONRPCForbidden()

    if UserGroupModel().get_by_name(group_name):
        raise JSONRPCError("user group `%s` already exist" % (group_name,))

    try:
        if isinstance(owner, Optional):
            owner = apiuser.user_id

        owner = get_user_or_error(owner)
        active = Optional.extract(active)
        description = Optional.extract(description)
        ug = UserGroupModel().create(
            name=group_name, description=description, owner=owner,
            active=active)
        Session().commit()
        return {
            'msg': 'created new user group `%s`' % group_name,
            'user_group': ug.get_api_data()
        }
    except Exception:
        log.exception("Error occurred during creation of user group")
        raise JSONRPCError('failed to create group `%s`' % (group_name,))
Пример #16
0
def get_locks(request, apiuser, userid=Optional(OAttr('apiuser'))):
    from .user_api import get_user_locks
    return get_user_locks(request=request, apiuser=apiuser, userid=userid)
def merge_pull_request(request,
                       apiuser,
                       repoid,
                       pullrequestid,
                       userid=Optional(OAttr('apiuser'))):
    """
    Merge the pull request specified by `pullrequestid` into its target
    repository.

    :param apiuser: This is filled automatically from the |authtoken|.
    :type apiuser: AuthUser
    :param repoid: The Repository name or repository ID of the
        target repository to which the |pr| is to be merged.
    :type repoid: str or int
    :param pullrequestid: ID of the pull request which shall be merged.
    :type pullrequestid: int
    :param userid: Merge the pull request as this user.
    :type userid: Optional(str or int)

    Example output:

    .. code-block:: bash

      "id": <id_given_in_input>,
      "result":
        {
            "executed":         "<bool>",
            "failure_reason":   "<int>",
            "merge_commit_id":  "<merge_commit_id>",
            "possible":         "<bool>"
        },
      "error": null

    """
    repo = get_repo_or_error(repoid)
    if not isinstance(userid, Optional):
        if (has_superadmin_permission(apiuser)
                or HasRepoPermissionAnyApi('repository.admin')(
                    user=apiuser, repo_name=repo.repo_name)):
            apiuser = get_user_or_error(userid)
        else:
            raise JSONRPCError('userid is not the same as your user')

    pull_request = get_pull_request_or_error(pullrequestid)
    if not PullRequestModel().check_user_merge(pull_request, apiuser,
                                               api=True):
        raise JSONRPCError('repository `%s` does not exist' % (repoid, ))
    if pull_request.is_closed():
        raise JSONRPCError(
            'pull request `%s` merge failed, pull request is closed' %
            (pullrequestid, ))

    target_repo = pull_request.target_repo
    extras = vcs_operation_context(request.environ,
                                   repo_name=target_repo.repo_name,
                                   username=apiuser.username,
                                   action='push',
                                   scm=target_repo.repo_type)
    data = PullRequestModel().merge(pull_request, apiuser, extras=extras)
    if data.executed:
        PullRequestModel().close_pull_request(pull_request.pull_request_id,
                                              apiuser)

        Session.commit()
    return data