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
|
= ArchiveAuthToken =
This content class represents an authorisation token associated with
an IPerson and an IArchive. The tokens are used to permit Launchpad
users access to a published private archive and are written out to
.htaccess files in the archive's filesystem by the publisher.
See also ArchiveSubscriber.txt.
First we create a private PPA for Joe.
>>> login("admin@canonical.com")
>>> joe = factory.makePerson(name="joe", displayname="Joe Smith")
>>> joe_private_ppa = factory.makeArchive(
... owner=joe, private=True, name='ppa')
== Creating new tokens ==
New tokens are created using IArchive.newAuthToken() but this is only
possible if there is already a valid subscription for the user for
that archive.
Create Brad, and his team:
>>> login("admin@canonical.com")
>>> bradsmith = factory.makePerson(
... name="bradsmith", displayname="Brad Smith", password="test",
... email="brad@example.com")
>>> teambrad = factory.makeTeam(
... owner=bradsmith, displayname="Team Brad", name='teambrad')
Create a subscription for Team Brad to joe's archive:
>>> login_person(joe)
>>> subscription_to_joe_private_ppa = joe_private_ppa.newSubscription(
... teambrad, joe)
>>> login("brad@example.com")
It is not possible to create a token for the subscribed team.
>>> joe_private_ppa.newAuthToken(teambrad)
Traceback (most recent call last):
...
NoTokensForTeams: Subscription tokens can be created for individuals
only.
But now that the subscription is there, we can create a token as Brad.
>>> token_with_random_string = joe_private_ppa.newAuthToken(bradsmith)
By default the tokens are 20 characters long.
>>> print len(token_with_random_string.token)
20
It is not possible to create a second token when one already exists:
>>> new_token = joe_private_ppa.newAuthToken(bradsmith)
Traceback (most recent call last):
...
ArchiveSubscriptionError: Brad Smith already has a token for
PPA for Joe Smith.
So deactivate the old token so that we can create a new token:
>>> login_person(bradsmith)
>>> token_with_random_string.deactivate()
>>> login("brad@example.com")
We can also specify our own token for testing purposes:
>>> new_token = joe_private_ppa.newAuthToken(bradsmith, u"testtoken")
The new token is returned and reflects the data:
>>> print new_token.archive.displayname
PPA for Joe Smith
>>> print new_token.person.name
bradsmith
>>> print new_token.token
testtoken
>>> print new_token.archive_url
http://bradsmith:testtoken@private-ppa.launchpad.dev/joe/ppa/...
Commit the new token to the database.
>>> from storm.store import Store
>>> Store.of(new_token).commit()
Tokens also contain some date information:
>>> new_token.date_created is not None
True
>>> print new_token.date_deactivated
None
== Retrieving existing tokens ==
The ArchiveAuthTokenSet utility allows you to retrieve tokens by ID and by
the token text itself. To access tokens you need launchpad.View privilege
which applies to the person in the token and launchpad admins.
>>> from lp.soyuz.interfaces.archiveauthtoken import (
... IArchiveAuthTokenSet)
>>> token_set = getUtility(IArchiveAuthTokenSet)
>>> login("no-priv@canonical.com")
>>> token = token_set.get(new_token.id)
Traceback (most recent call last):
...
Unauthorized:...
Log in as Brad Smith, who is the person in the token.
>>> login("brad@example.com")
And retrieve the token by id and by token data:
>>> print token_set.get(new_token.id).token
testtoken
>>> print token_set.getByToken(u"testtoken").person.name
bradsmith
It's also possible to retrieve a set of all the tokens for an archive.
>>> tokens = token_set.getByArchive(joe_private_ppa)
>>> print tokens.count()
1
>>> for token in tokens:
... print token.person.name
bradsmith
Tokens can also be retreived by archive and person:
>>> print token_set.getActiveTokenForArchiveAndPerson(
... new_token.archive, new_token.person).token
testtoken
== Amending Tokens ==
Tokens can only be de-activated after they are created. The calling user
also needs launchpad.Edit on the token, which means either someone with
IArchive launchpad.Append (as for creating new tokens) or an admin.
>>> login("no-priv@canonical.com")
>>> new_token.deactivate()
Traceback (most recent call last):
...
Unauthorized:...
>>> login_person(joe)
>>> new_token.deactivate()
Deactivating sets the date_deactivated value.
>>> new_token.date_deactivated is not None
True
We can do this as an admin too:
>>> new_token = joe_private_ppa.newAuthToken(bradsmith)
>>> login("admin@canonical.com")
>>> new_token.deactivate()
Deactivating a token stops it being returned from getByArchive(). The
previous count of 1 is now reduced to 0.
>>> token_set.getByArchive(joe_private_ppa).count()
0
The IArchiveAuthTokenSet.getActiveTokenForArchiveAndPerson() method will
also not return tokens that have been deactivated:
>>> print token_set.getActiveTokenForArchiveAndPerson(
... new_token.archive, new_token.person)
None
|