aboutsummaryrefslogtreecommitdiffstats
path: root/lib/python2.7/site-packages/buildbot-0.8.8-py2.7.egg/buildbot/process/users/manual.py
blob: be94a691089166ae7c77324c5f4128a1731d8ebf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
# This file is part of Buildbot.  Buildbot is free software: you can
# redistribute it and/or modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation, version 2.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Copyright Buildbot Team Members

# this class is known to contain cruft and will be looked at later, so
# no current implementation utilizes it aside from scripts.runner.

from twisted.python import log
from twisted.internet import defer
from twisted.application import service
from buildbot import pbutil

class UsersBase(service.MultiService):
    """
    Base class for services that manage users manually. This takes care
    of the service.MultiService work needed by all the services that
    subclass it.
    """

    def __init__(self):
        service.MultiService.__init__(self)
        self.master = None

    def startService(self):
        service.MultiService.startService(self)

    def stopService(self):
        return service.MultiService.stopService(self)

class CommandlineUserManagerPerspective(pbutil.NewCredPerspective):
    """
    Perspective registered in buildbot.pbmanager and contains the real
    workings of `buildbot user` by working with the database when
    perspective_commandline is called.
    """

    def __init__(self, master):
        self.master = master

    def formatResults(self, op, results):
        """
        This formats the results of the database operations for printing
        back to the caller

        @param op: operation to perform (add, remove, update, get)
        @type op: string

        @param results: results from db queries in perspective_commandline
        @type results: list

        @returns: string containing formatted results
        """
        formatted_results = ""

        if op == 'add':
            # list, alternating ident, uid
            formatted_results += "user(s) added:\n"
            for user in results:
                if isinstance(user, basestring):
                    formatted_results += "identifier: %s\n" % user
                else:
                    formatted_results += "uid: %d\n\n" % user
        elif op == 'remove':
            # list of dictionaries
            formatted_results += "user(s) removed:\n"
            for user in results:
                if user:
                    formatted_results += "identifier: %s\n" % (user)
        elif op == 'update':
            # list, alternating ident, None
            formatted_results += "user(s) updated:\n"
            for user in results:
                if user:
                    formatted_results += "identifier: %s\n" % (user)
        elif op == 'get':
            # list of dictionaries
            formatted_results += "user(s) found:\n"
            for user in results:
                if user:
                    for key in user:
                        if key != 'bb_password':
                            formatted_results += "%s: %s\n" % (key, user[key])
                    formatted_results += "\n"
                else:
                    formatted_results += "no match found\n"
        return formatted_results

    @defer.inlineCallbacks
    def perspective_commandline(self, op, bb_username, bb_password, ids, info):
        """
        This performs the requested operations from the `buildbot user`
        call by calling the proper buildbot.db.users methods based on
        the operation. It yields a deferred instance with the results
        from the database methods.

        @param op: operation to perform (add, remove, update, get)
        @type op: string

        @param bb_username: username portion of auth credentials
        @type bb_username: string

        @param bb_password: hashed password portion of auth credentials
        @type bb_password: hashed string

        @param ids: user identifiers used to find existing users
        @type ids: list of strings or None

        @param info: type/value pairs for each user that will be added
                     or updated in the database
        @type info: list of dictionaries or None

        @returns: results from db.users methods via deferred
        """
        log.msg("perspective_commandline called")
        results = []

        if ids:
            for user in ids:
                # get identifier, guaranteed to be in user from checks
                # done in C{scripts.runner}
                uid = yield self.master.db.users.identifierToUid(
                                            identifier=user)

                result = None
                if op == 'remove':
                    if uid:
                        yield self.master.db.users.removeUser(uid)
                        result = user
                    else:
                        log.msg("Unable to find uid for identifier %s" % user)
                elif op == 'get':
                    if uid:
                        result = yield self.master.db.users.getUser(uid)
                    else:
                        log.msg("Unable to find uid for identifier %s" % user)

                results.append(result)
        else:
            for user in info:
                # get identifier, guaranteed to be in user from checks
                # done in C{scripts.runner}
                ident = user.pop('identifier')
                uid = yield self.master.db.users.identifierToUid(
                                                 identifier=ident)

                # if only an identifier was in user, we're updating only
                # the bb_username and bb_password.
                if not user:
                    if uid:
                        result = yield self.master.db.users.updateUser(
                                                       uid=uid,
                                                       identifier=ident,
                                                       bb_username=bb_username,
                                                       bb_password=bb_password)
                        results.append(ident)
                    else:
                        log.msg("Unable to find uid for identifier %s"
                                % user)
                else:
                    # when adding, we update the user after the first attr
                    once_through = False
                    for attr in user:
                        if op == 'update' or once_through:
                            if uid:
                                result = yield self.master.db.users.updateUser(
                                                      uid=uid,
                                                      identifier=ident,
                                                      bb_username=bb_username,
                                                      bb_password=bb_password,
                                                      attr_type=attr,
                                                      attr_data=user[attr])
                            else:
                                log.msg("Unable to find uid for identifier %s"
                                        % user)
                        elif op == 'add':
                            result = yield self.master.db.users.findUserByAttr(
                                                      identifier=ident,
                                                      attr_type=attr,
                                                      attr_data=user[attr])
                            once_through = True
                        results.append(ident)

                        # result is None from updateUser calls
                        if result:
                            results.append(result)
                            uid = result
        results = self.formatResults(op, results)
        defer.returnValue(results)

class CommandlineUserManager(UsersBase):
    """
    Service that runs to set up and register CommandlineUserManagerPerspective
    so `buildbot user` calls get to perspective_commandline.
    """

    def __init__(self, username=None, passwd=None, port=None):
        UsersBase.__init__(self)
        assert username and passwd, ("A username and password pair must be given "
                                     "to connect and use `buildbot user`")
        self.username = username
        self.passwd = passwd

        assert port, "A port must be specified for a PB connection"
        self.port = port
        self.registration = None

    def startService(self):
        UsersBase.startService(self)
        # set up factory and register with buildbot.pbmanager
        def factory(mind, username):
            return CommandlineUserManagerPerspective(self.master)
        self.registration = self.master.pbmanager.register(self.port,
                                                           self.username,
                                                           self.passwd,
                                                           factory)

    def stopService(self):
        d = defer.maybeDeferred(UsersBase.stopService, self)
        def unreg(_):
            if self.registration:
                return self.registration.unregister()
        d.addCallback(unreg)
        return d