Commit 8cf66d7f authored by Roman Lacko's avatar Roman Lacko
Browse files

Initial commit (v8.12.1)

parents
Loading
Loading
Loading
Loading

GitLab.pm

0 → 100644
+167 −0
Original line number Original line Diff line number Diff line
package GitLab;

use strict;
use warnings;

use Log::Any    qw($log);

use Carp;
use GitLab::API;
use GitLab::Groups;
use GitLab::Namespaces;
use GitLab::Users;
use Try::Tiny;

use parent "Exporter";

our @EXPORT_OK      = ();
our %EXPORT_TAGS    = (
    group_visibility => [ qw|GROUP_VISIBILITY    GROUP_PRIVATE GROUP_INTERNAL  GROUP_PUBLIC | ],
    member_access    => [ qw|MEMBER_ACCESS       MEMBER_GUEST  MEMBER_REPORTER MEMBER_DEVELOPER MEMBER_MASTER MEMBER_OWNER | ],
    utils            => [ qw|group_visibility_name   member_access_name| ],
);

Exporter::export_ok_tags(qw|group_visibility member_access utils|);

#===============================================================================
#   Constants
#===============================================================================

use constant {
    # Group Visibility
    GROUP_PRIVATE       => 00,
    GROUP_INTERNAL      => 10,
    GROUP_PUBLIC        => 20,

    # Member rights
    MEMBER_GUEST        => 10,
    MEMBER_REPORTER     => 20,
    MEMBER_DEVELOPER    => 30,
    MEMBER_MASTER       => 40,
    MEMBER_OWNER        => 50,
};

use constant GROUP_VISIBILITY
    => (GROUP_PRIVATE, GROUP_INTERNAL, GROUP_PUBLIC);
use constant MEMBER_ACCESS
    => (MEMBER_GUEST, MEMBER_REPORTER, MEMBER_DEVELOPER, MEMBER_MASTER, MEMBER_OWNER);

#===============================================================================
#   Utilities
#===============================================================================

my %group_visibility_map = (
    "10" => "Private",
    "20" => "Internal",
    "30" => "Public",
);

sub group_visibility_name {
    my ($code) = @_;
    return $group_visibility_map{$code} // "Invalid";
}

my %member_access_map = (
    "10" => "Guest",
    "20" => "Reporter",
    "30" => "Developer",
    "40" => "Master",
    "50" => "Owner",
);

sub member_access_name {
    my ($code) = @_;
    return $member_access_map{$code} // "Invalid";
}

1;

__END__

=head1 NAME

    GitLab - convenience wrapper for GitLab::API that provides useful constants

=head1 SYNOPSIS

    use GitLab qw(:utils);

    my $gitlab = GitLab::API->new(...);
    my $users  = $gitlab->users();

=head1 DESCRIPTION

=head2 Constants

The module defines access level constants. See appropriate API documentation
for explanation.

=head3 Group visibility

Import with C<:group_visibility> tag.

    10 GROUP_PRIVATE
    20 GROUP_INTERNAL
    30 GROUP_PUBLIC

=head3 Member access

Import with C<:member_access> tag.

    10 MEMBER_GUEST
    20 MEMBER_REPORTER
    30 MEMBER_DEVELOPER
    40 MEMBER_MASTER
    50 MEMBER_OWNER

=head2 Utilities

Import with C<:utils> tag.

=over

=item group_visibility_name()

    $name = GitLab::group_visibility_name($code)

Translates a Group Visibility code to its string representation, i.e. I<Private>, I<Internal> or I<Public>.
If the parameter does not represent a valid GitLab Group Visibility code, returns I<Invalid>.

=item member_access_name()

    $name = GitLab::member_access_name($code);

Translates a Member Access code to its string representation, i.e. I<Guest>, I<Reporter>, I<Developer>, I<Master> and I<Owner>.
If the parameter does not represent a valid GitLab Member Access code, returns I<Invalid>.

=back

=head1 AUTHOR

Roman Lacko <L<xlacko1@fi.muni.cz>>

=head1 SEE ALSO

=over

=item L<GitLab::API::v3>

Complete GitLab API v3 implementation with CLI support.

=item L<GitLab::API>

implementation of the L<GitLab API|http://docs.gitlab.com/ce/api/> client.

=item L<GitLab::Groups>

L<GitLab Groups|http://docs.gitlab.com/ce/api/groups.html> methods.

=item L<GitLab::Namespaces>

L<GitLab Namespaces|http://docs.gitlab.com/ce/api/namespaces.html> methods.

=item L<GitLab::Users>

L<GitLab Users|http://docs.gitlab.com/ce/api/users.html> methods.

=back

GitLab/API.pm

0 → 100644
+0 −0

File added.

Preview size limit exceeded, changes collapsed.

GitLab/Groups.pm

0 → 100644
+222 −0
Original line number Original line Diff line number Diff line
package GitLab::Groups;

use utf8;
use strict;
use warnings;
use vars qw($VERSION);

use GitLab::API;
use Log::Any        qw($log);

our $VERSION = v8.12.1;

my $requests = {
    groups  => {
        method      => "GET",
        path        => "/groups",
        query       => [ qw(search) ],
        paginated   => 1,
    },

    group_get_projects => {
        method      => "GET",
        path        => "/groups/<gid>/projects",
        optional    => [ qw(archived visibility order_by sort search ci_enabled_first) ],
        paginated   => 1,
    },

    group_details => {
        method      => "GET",
        path        => "/groups/<gid>",
    },

    group_create => {
        method      => "POST",
        path        => "/groups",
        required    => [ qw(name path) ],
        optional    => [ qw(description visibility_level lfs_enabled request_access_enabled) ],
    },

    transfer_project_to_group => {
        method      => "POST",
        path        => "/groups/<gid>/projects/<projid>",
    },

    group_update => {
        method      => "PUT",
        path        => "/groups/<gid>",
        optional    => [ qw(name path description visibility_level lfs_enabled request_access_enabled) ],
    },

    group_delete    => {
        method      => "DELETE",
        path        => "/groups/<gid>",
    },

    group_members   => {
        method      => "GET",
        path        => "/groups/<gid>/members",
        paginated   => 1,
    },

    group_add_member => {
        method      => "POST",
        path        => "/groups/<gid>/members",
        required    => [ qw!user_id access_level! ],
    },

    group_update_member => {
        method      => "PUT",
        path        => "/groups/<gid>/members/<user_id>",
        required    => [ qw!access_level! ],
    },

    group_delete_member => {
        method      => "DELETE",
        path        => "/groups/<gid>/members/<user_id>",
    },
};

sub import {
    $log->debug("initializing " . __PACKAGE__);
    while (my ($name, $tmpl) = each(%$requests)) {
        $tmpl->{name} = $name unless exists $tmpl->{name};
        GitLab::API->register($tmpl);
    }
}

1;

__END__

=head1 NAME

GitLab::Groups - implements group API calls

See L<GitLab API -- Groups|http://doc.gitlab.com/ce/api/groups.html> for details and
response formats.

=head1 VERSION

Implements API calls for GitLab CE C<v8.10.0>.
Checked 2016-09-29 for GitLab CE C<v8.12.1>.

=head1 DESCRIPTION

=head2 Notation

Please see the documentation for the L<GitLab::Users> module.

Note that not all optional arguments are listed.
Please refer to the official documentation for the full list.

=head2 Group CRUD operations

=over

=item groups()

    $groups = $gitlab->groups( [:search] );

Returns a list of groups.
An optional parameter C<search> can be used to filter the list by substring match on C<name>.

=item group_details()

    $details = $gitlab->group_details( :gid );

Returns details about a group with the given C<gid>.

=item group_create()

    $group = $gitlab->group_create( :name, :path, [:description], [:visibility_level] );

Creates a new group. Required arguments are

    name                the name of the group,
    path                the path for the group (must be unique)

In addition, the following I<optional> arguments can be specified:

    description         group's description
    visibility_level    see GitLab::API for possible values

=item group_update()

    $group = $gitlab->group_update( :gid );

Updates the grup with the given C<gid>.
Takes same arguments as C<group_create>, except they are all optional.

=item group_delete()

    $gitlab->group_delete( :gid );

Deletes the group with the given C<gid>.

=back

=head2 Group members

=over

=item group_members()

    $members = $gitlab->group_members( :gid );

Returns a list of members in the grup with the specified C<gid>.

=item group_add_member()

    $gitlab->group_add_member( :gid, :user_id, :access_level );

Adds a user with C<user_id> to the group with the given C<gid> with the specified C<access_level>.
See L<GitLab::API> module for possible access level values.

=item group_update_member()

    $gitlab->group_update_member( :gid, :user_id, :access_level );

For user with the given C<user_id> the function changes his C<access_level> in the group with the specified C<gid>.

=item group_delete_member()

    $gitlab->group_delete_member( :gid, :user_id );

Removes the user with C<user_id> from the group with the specified C<gid>.

=back

=head2 Group projects and transfer

=over

=item group_get_projects()

    $projects = $gitlab->group_get_projects( :gid );

Returns a list of projects owned by the group with the given C<gid>.

=item transfer_project_to_group()

    $gitlab->transfer_project_to_group( :gid, :projid );

Moves the project with C<projid> to the namespace of the group with the given C<gid>.

I<This method is available only for administrators.>

=back

=head1 AUTHOR

Roman Lacko <L<xlacko1@fi.muni.cz>>

=head1 SEE ALSO

=over

=item L<GitLab>

Wrapper around L<GitLab::API> and other C<GitLab::*> modules.

=back

GitLab/Namespaces.pm

0 → 100644
+93 −0
Original line number Original line Diff line number Diff line
package GitLab::Namespaces;

use utf8;
use strict;
use warnings;
use vars qw($VERSION);

use GitLab::API;
use Log::Any        qw($log);

our $VERSION = v8.12.1;

my $requests = {
    namespaces => {
        method      => "GET",
        path        => "/namespaces",
        query       => [ qw(search) ],
        paginated   => 1,
    }
};

sub import {
    $log->debug("initializing " . __PACKAGE__);
    while (my ($name, $tmpl) = each(%$requests)) {
        $tmpl->{name} = $name unless exists $tmpl->{name};
        GitLab::API->register($tmpl);
    }
}

1;

__END__

=head1 NAME

GitLab::Namespaces - extension for Namespaces API

See L<GitLab API -- Namespaces|http://doc.gitlab.com/ce/api/namespaces.html> for details and response formats.

=head1 SYNOPSIS

    use GitLab::API;
    use GitLab::Namespaces;

    my $api = GitLab::API->new();

    # get namespaces exposed to user john.doe
    $api->sudo("john.doe");

    my $namespaces = $api->namespaces(search => "group1");

=head1 VERSION

Implements API calls for GitLab CE C<v8.10.0>.
Checked 2016-09-29 for GitLab CE C<v8.12.1>.

=head1 DESCRIPTION

From GitLab API: I<"Usernames and groupnames fall under a special category called namespaces.">

=over

=item namespaces()

    $namespaces = $gitlab->namespaces();
    $namespaces = $gitlab->namespaces(search => $what);

Returns all namespaces for currently authenticated user.
If an optional argument C<search> is used, only those namespaces that contain the requested string are returned.

To get namespaces of user with login C<$login>, you can do this:

    $gitlab->sudo($login);
    $namespaces = $gitlab->namespaces();

Note that the authenticated user must be an administrator to use L<GitLab::API/sudo>.
If the user with login C<$login> is an administrator, the call will return B<all> namespaces.

=back

=head1 AUTHOR

Roman Lacko <L<xlacko1@fi.muni.cz>>

=head1 SEE ALSO

=over

=item L<GitLab>

Wrapper around L<GitLab::API> and other C<GitLab::*> modules.

=back

GitLab/Users.pm

0 → 100644
+424 −0
Original line number Original line Diff line number Diff line
package GitLab::Users;

use utf8;
use strict;
use warnings;
use vars qw($VERSION);

use GitLab::API;
use Log::Any        qw($log);

our $VERSION = 8.12.1;

my $requests = {
    users => {
        method      => "GET",
        path        => "/users",
        query       => [ qw(username search) ],
        paginated   => 1,
    },

    user_by_id => {
        method      => "GET",
        path        => "/users/<uid>",
    },

    user_create     => {
        method      => "POST",
        path        => "/users",
        required    => [ qw(email password username name) ],
        optional    => [ qw(skype linkedin twitter website_url projects_limit
        extern_uid provider bio location admin confirm can_create_group external) ],
    },

    user_update     => {
        method      => "PUT",
        path        => "/users/<uid>",
        # update can cause Conflict, but API always returns 404
        ret         => { 404 => "Not found or Conflict" },
        optional    => [ qw(email password name username skype linkedin twitter
        website_url projects_limit extern_uid provider bio location admin can_create_group external) ],
    },

    user_delete     => {
        method      => "DELETE",
        path        => "/users/<uid>",
    },

    user => {
        method      => "GET",
        path        => "/user",
    },

    self_ssh_keys => {
        method      => "GET",
        path        => "/user/keys",
        paginated   => 1,
    },

    self_get_ssh_key => {
        method      => "GET",
        path        => "/user/keys/<keyid>",
    },

    user_get_ssh_keys => {
        method      => "GET",
        path        => "/users/<uid>/keys",
        paginated   => 1,
    },

    self_add_ssh_key => {
        method      => "POST",
        path        => "/user/keys",
        required    => [ qw!title key! ],
    },

    user_add_ssh_key => {
        method      => "POST",
        path        => "/users/<uid>/keys",
        required    => [ qw!title key! ],
    },

    self_delete_ssh_key => {
        method      => "DELETE",
        path        => "/user/keys/<keyid>",
    },

    user_delete_ssh_key => {
        method      => "DELETE",
        path        => "/users/<uid>/keys/<keyid>",
    },

    self_get_emails => {
        method      => "GET",
        path        => "/user/emails",
        paginated   => 1,
    },

    user_get_emails => {
        method      => "GET",
        path        => "/users/<uid>/emails",
        paginated   => 1,
    },

    self_get_email => {
        method      => "GET",
        path        => "/user/emails/<eid>",
    },

    # not officially supported, may not work :(
    # user_get_email => {
    #     method      => "GET",
    #     path        => "/users/<uid>/emails/<eid>",
    # },

    self_add_email => {
        method      => "POST",
        path        => "/user/emails",
        required    => [ qw!email! ],
    },

    user_add_email => {
        method      => "POST",
        path        => "/users/<uid>/emails",
        required    => [ qw!email! ],
    },

    self_delete_email => {
        method      => "DELETE",
        path        => "/user/emails/<eid>",
    },

    user_delete_email => {
        method      => "DELETE",
        path        => "/users/<uid>/emails/<eid>",
    },

    user_block      => {
        method      => "PUT",
        path        => "/users/<uid>/block",
    },

    user_unblock    => {
        method      => "PUT",
        path        => "/users/<uid>/unblock",
    },
};

sub import {
    $log->debug("initializing " . __PACKAGE__);
    while (my ($name, $tmpl) = each(%$requests)) {
        $tmpl->{name} = $name unless exists $tmpl->{name};
        GitLab::API->register($tmpl);
    }
}

1;

__END__

=head1 NAME

GitLab::Users - implements user API calls

See L<GitLab API -- Users|http://doc.gitlab.com/ce/api/users.html> for details and
response formats.

=head1 VERSION

Implements API calls for GitLab CE C<v8.10.0>.
Checked 2016-09-29 for GitLab CE C<v8.12.1>.

=head1 SYNOPSIS

    use GitLab::API;
    use GitLab::Users;
    # all calls from GitLab::Users are "injected" into the GitLab::API as methods

    my $api = GitLab::API->new();

    my $john = $api->users(username => "john_doe");

    $api->user_create(
        email       => "jane34@somewhere.com",
        password    => "s3cre1",
        username    => "jane.doe",
        name        => "Jane Doe"
    );

=head1 DESCRIPTION

=head2 Notation

All methods take a hash of arguments as specified in the documentation for
L<GitLab::API/exec_request>, but to simplify the documentation,
we will use the following notation:

    users( :username, :search )

which means that the C<users> method takes a hash with two keys, C<username>
and C<search>, so it can be called as

    $gitlab->users(search => "john_doe");

Optional arguments are denoted as C< [:username] >.
Note that not all optional arguments are listed.
Please refer to the official documentation for the full list.

=head2 User CRUD operations

=over

=item users()

    $users = $gitlab->users( [:username], [:search] );

This method returns all users. The optional arguments can be used
to filter out the results:

    username        search for a user by his username (exact match)
    search          search for users with username or email (substring match)

Note that the returned value is still an array even when C<< users(username => $username) >>
always returns at most one result.

=item user_by_id()

    $user = $gitlab->user_by_id( :uid );

Returns a user with the given C<uid>.

=item user_create()

    $user = $gitlab->user_create( :email, :password, :username, :name );

Creates a new user and if succeeds, returns the generated account information.

    email               primary email, must not exist in GitLab,
    password            user password,
    username            login, must not exist in GitLab,
    name                display name

The function can take many optional arguments. Please see the API documentation for
the full list. Most interesting arguments are:

    admin               create an admin account (bool)
    can_create_group    the user will be able to create group (bool)
    external            create an external account (bool)
    projects_limit      maximum number of projects the user can own

=item user_update()

    $user = $gitlab->user_update( :uid );

Updates the user with the given C<uid>. It takes the same arguments as C<user_create>
except they are all optional. Note that though it is possible to change user's primary e-mail
and username, it is probably not a very sane thing to do.

Also, from documentation:

    Note, at the moment this method does only return a 404 error, even in cases where
    a 409 (Conflict) would be more appropriate, e.g. when renaming the email address to some existing one.

=item user_delete()

    $gitlab->user_delete( :uid );

Deletes the user with the given C<uid>.

Note that

    calling this function for a non-existent user id still returns a status code 200 OK.
    The JSON response differs if the user was actually deleted or not.

(from the GitLab API documentation).

=item user()

    $user = $gitlab->user();

Returns the user whose authentication key is used for the request
(or impersonated user if C<sudo> is in effect).

Behaves the same as the L<GitLab::API/whoami> method.

=back

=head2 SSH keys

=over

=item self_ssh_keys()

    $keys = $gitlab->self_ssh_keys();

Returns a list of SSH keys for the user that makes the request.

=item self_get_ssh_key()

    $key = $gitlab->self_get_ssh_key( :keyid );

For the user that makes the request, the function returns the SSH key with the given C<keyid>.

=item user_get_ssh_keys()

    $keys = $gitlab->user_get_ssh_keys( :uid );

Returns a list of SSH keys for the user with the given C<uid>.

=item self_add_ssh_key()

    $key = $gitlab->self_add_ssh_key( :title, :key );

Adds a new key for the user that makes the request. Required arguments are

    title               the title of the key
    key                 public SSH key

=item user_add_ssh_key()

    $key = $gitlab->user_add_ssh_key( :uid, :title, :key );

Similar to C<self_add_ssh_key>, but targets the user with the given C<uid>.

=item self_delete_ssh_key()

    $gitlab->self_delete_ssh_key( :keyid )

Removes the SSH key with the given C<keyid> for the user that makes the request.

=item user_delete_ssh_key()

    $gitlab->user_delete_ssh_key( :uid, :keyid );

Removes the SSH key with the C<keyid> for the user with the given C<uid>.

=back

=head2 E-mails

=over

=item self_get_emails()

    $emails = $gitlab->self_get_emails();

Returns a list of B<secondary> e-mails for the user that makes the request.

Note that primary e-mail can be obtained from the result of C<whoami>.

=item user_get_emails()

    $emails = $gitlab->user_get_emails( :uid );

Returns a list of B<secondary> e-mails for the user with the C<uid>.

Note that primary e-mail can be obtained from the result of C<user_by_id>.

=item self_get_email()

    $email = $gitlab->self_get_email( :eid );

Returns the e-mail with the given C<eid> of the user that makes the request.

=item self_add_email()

    $email = $gitlab->self_add_email( :email );

Adds a new C<email> for the user that makes the request. The e-mail must
not exist in GitLab.

=item user_add_email()

    $email = $gitlab->user_add_email( :uid, :email );

Adds a new C<email> for the user with the given C<uid>. The e-mail must
not exist in GitLab.

=item self_delete_email()

    $gitlab->self_delete_email( :eid );

Deletes the e-mail with C<eid> of the user that makes the request.

=item user_delete_email()

    $gitlab->user_delete_email( :uid, :eid );

Removes the e-mail with C<eid> of the user with the given C<uid>.

=back

=head2 Account blocking

=over

=item user_block()

    $gitlab->user_block( :uid );

Blocks the user with C<uid> in the GitLab.

=item user_unblock()

    $gitlab->user_unblock( :uid );

Unblocks the user with C<uid> in the GitLab.
Note that LDAP blocked users cannot be unblocked by this function.
In that case the API would return C<403 Forbidden>.

=back

=head1 AUTHOR

Roman Lacko <L<xlacko1@fi.muni.cz>>

=head1 SEE ALSO

=over

=item L<GitLab>

Wrapper around L<GitLab::API> and other C<GitLab::*> modules.

=back