Skip to content

Commit 74f4de8

Browse files
committed
Add API for token management
1 parent 8ca42a1 commit 74f4de8

File tree

3 files changed

+133
-2
lines changed

3 files changed

+133
-2
lines changed

docs/examples.rst

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,3 +46,29 @@ Below is an example demonstrating how to update a user (requires admin privilege
4646
"username_to_update",
4747
update)
4848

49+
50+
Example 3: Creating a token
51+
---------------------------
52+
53+
Below is an example illustrating how to create a token for you application::
54+
55+
import gogs_client
56+
from getpass import getpass
57+
from platform import node
58+
59+
api = GogsApi("https://try.gogs.io/")
60+
61+
try: token_str = open("tokenfile.txt","r").read()
62+
except OSError: token_str = None
63+
if token_str:
64+
token = gogs_client.Token(token_str)
65+
else:
66+
username = input("username> ")
67+
password = getpass("password> ")
68+
login = gogs_client.UsernamePassword(username, password)
69+
token = api.ensure_token(login, "my cool app on "+node(), username)
70+
open("tokenfile.txt", "w".write(token.token))
71+
72+
username = api.authenticated_user(token)
73+
print("User {} authenticated by token {}".format(username, token_str))
74+

gogs_client/entities.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,3 +240,46 @@ def pull(self):
240240
:rtype: bool
241241
"""
242242
return self._pull
243+
244+
245+
class TokenInfo(object):
246+
"""
247+
An immutable representation of a Gogs user token information
248+
"""
249+
250+
def __init__(self, name, sha1):
251+
self._name = name
252+
self._sha1 = sha1
253+
254+
@staticmethod
255+
def from_json(cls, parsed_json):
256+
name = json_get(parsed_json, "name")
257+
sha1 = json_get(parsed_json, "sha1")
258+
return TokenInfo(name, sha1)
259+
260+
@property
261+
def name(self):
262+
"""
263+
The name of the token
264+
265+
:rtype: str
266+
"""
267+
return self._name
268+
269+
@property
270+
def sha1(self):
271+
"""
272+
The hash of the token
273+
274+
:rtype: str
275+
"""
276+
return self._sha1
277+
278+
def as_token(self):
279+
"""
280+
Create Token authenticator for this token
281+
282+
:rtype: gogs_client.auth.Token
283+
"""
284+
from gogs_client.auth import Token
285+
return Token(self.sha1)

gogs_client/interface.py

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import requests
22

33
from gogs_client._implementation.http_utils import RelativeHttpRequestor, append_url
4-
from gogs_client.entities import GogsUser, GogsRepo
4+
from gogs_client.entities import GogsUser, GogsRepo, TokenInfo
55

66

77
class GogsApi(object):
88
"""
9-
A Gogs client, serving as a wrapper around the Gogs HTTP API.
9+
A Gogs API entries, serving as a wrapper around the Gogs HTTP API.
1010
"""
1111

1212
def __init__(self, base_url):
@@ -42,6 +42,68 @@ def authenticated_user(self, auth):
4242
response = self._get("/user", auth=auth)
4343
return GogsUser.from_json(self._check_ok(response).json())
4444

45+
def get_tokens(self, auth, username=None):
46+
"""
47+
Returns tokens defined for specified user.
48+
If no user specified uses user authenticated by the given authentication.
49+
Right now, authentication must be UsernamePassword (not Token).
50+
51+
:param auth.Authentication auth: authentication for user to retrieve
52+
:param str username: username of owner of tokens
53+
54+
:return: list of token info representation
55+
:rtype: List[TokenInfo]
56+
:raises NetworkFailure: if there is an error communicating with the server
57+
:raises ApiFailure: if the request cannot be serviced
58+
"""
59+
if username is None:
60+
username = self.authenticated_user(auth).username
61+
response = self._get("/users/{u}/tokens".format(u=username), auth=auth)
62+
return [TokenInfo.from_json(o) for o in self._check_ok(response).json()]
63+
64+
def create_token(self, auth, name, username=None):
65+
"""
66+
Creates new token with specified name for specified user.
67+
If no user specified uses user authenticated by the given authentication.
68+
Right now, authentication must be UsernamePassword (not Token).
69+
70+
:param auth.Authentication auth: authentication for user to retrieve
71+
:param str name: name of new token
72+
:param str username: username of owner of new token
73+
74+
:return: representation of token info
75+
:rtype: TokenInfo
76+
:raises NetworkFailure: if there is an error communicating with the server
77+
:raises ApiFailure: if the request cannot be serviced
78+
"""
79+
if username is None:
80+
username = self.authenticated_user(auth).username
81+
data = {"name": name}
82+
response = self._post("/users/{u}/tokens".format(u=username), auth=auth, data=data)
83+
return TokenInfo.from_json(self._check_ok(response).json())
84+
85+
def ensure_token(self, auth, name, username=None):
86+
"""
87+
Creates new token if token with specified name for specified user does not exists.
88+
If no user specified uses user authenticated by the given authentication.
89+
Right now, authentication must be UsernamePassword (not Token).
90+
91+
:param auth.Authentication auth: authentication for user to retrieve
92+
:param str name: name of new token
93+
:param str username: username of owner of new token
94+
95+
:return: token authenticator
96+
:rtype: Token
97+
:raises NetworkFailure: if there is an error communicating with the server
98+
:raises ApiFailure: if the request cannot be serviced
99+
"""
100+
if username is None:
101+
username = self.authenticated_user(auth).username
102+
tokens = [token for token in self.get_tokens(auth, username) if token.name == name]
103+
if tokens:
104+
return tokens[0].as_token()
105+
return self.create_token(auth, name, username).as_token()
106+
45107
def create_repo(self, auth, name, description=None, private=False, auto_init=False,
46108
gitignore_templates=None, license_template=None, readme_template=None):
47109
"""

0 commit comments

Comments
 (0)