3
from gi.repository import GObject
11
import piston_mini_client.auth
13
from softwarecenter.enums import (SOFTWARE_CENTER_NAME_KEYRING,
14
SOFTWARE_CENTER_SSO_DESCRIPTION,
16
from softwarecenter.paths import SOFTWARE_CENTER_CACHE_DIR
17
from softwarecenter.backend.piston.scaclient import SoftwareCenterAgentAPI
18
from softwarecenter.backend.login_sso import get_sso_backend
19
from softwarecenter.backend.restfulclient import UbuntuSSOAPI
20
from softwarecenter.utils import clear_token_from_ubuntu_sso
22
from gettext import gettext as _
24
LOG = logging.getLogger(__name__)
26
class SSOLoginHelper(object):
27
def __init__(self, xid=0):
30
self.loop = GObject.MainLoop(GObject.main_context_default())
32
def _login_successful(self, sso_backend, oauth_result):
33
self.oauth = oauth_result
34
# FIXME: actually verify the token against ubuntu SSO
37
def verify_token(self, token):
38
def _whoami_done(sso, me):
42
sso = UbuntuSSOAPI(token)
43
sso.connect("whoami", _whoami_done)
44
sso.connect("error", lambda sso, err: self.loop.quit())
47
# check if the token is valid
48
if self._whoami is None:
53
def clear_token(self):
54
clear_token_from_ubuntu_sso(SOFTWARE_CENTER_NAME_KEYRING)
56
def get_oauth_token_sync(self):
58
sso = get_sso_backend(
60
SOFTWARE_CENTER_NAME_KEYRING,
61
_(SOFTWARE_CENTER_SSO_DESCRIPTION))
62
sso.connect("login-successful", self._login_successful)
63
sso.connect("login-failed", lambda s: self.loop.quit())
64
sso.connect("login-canceled", lambda s: self.loop.quit())
65
sso.login_or_register()
69
if __name__ == "__main__":
73
parser = argparse.ArgumentParser(description="Helper for software-center-agent")
74
parser.add_argument("--debug", action="store_true", default=False,
75
help="enable debug output")
76
parser.add_argument("--ignore-cache", action="store_true", default=False,
77
help="force ignore cache")
78
parser.add_argument("--parent-xid", default=0,
79
help="xid of the parent window")
81
subparser = parser.add_subparsers(title="Commands")
83
command = subparser.add_parser("available_apps")
84
command.add_argument("lang")
85
command.add_argument("series")
86
command.add_argument("arch")
87
command.set_defaults(command="available_apps")
90
command = subparser.add_parser("available_apps_qa")
91
command.add_argument("lang")
92
command.add_argument("series")
93
command.add_argument("arch")
94
command.set_defaults(command="available_apps_qa")
96
command = subparser.add_parser("subscriptions_for_me")
97
command.set_defaults(command="subscriptions_for_me")
99
command = subparser.add_parser("exhibits")
100
command.add_argument("lang")
101
command.add_argument("series")
102
command.set_defaults(command="exhibits")
104
args = parser.parse_args()
107
LOG.setLevel(logging.DEBUG)
109
if args.ignore_cache:
112
cachedir = os.path.join(SOFTWARE_CENTER_CACHE_DIR, "scaclient")
115
# check if auth is required
116
if args.command in ("available_apps_qa", "subscriptions_for_me"):
117
helper = SSOLoginHelper(args.parent_xid)
118
token = helper.get_oauth_token_sync()
119
# check if the token is valid and reset it if it is not
120
if token and not helper.verify_token(token):
123
token = helper.get_oauth_token_sync()
124
# if we don't have a token, error here
126
sys.stderr.write("ERROR: can not obtain a oauth token\n")
129
auth = piston_mini_client.auth.OAuthAuthorizer(token["token"],
130
token["token_secret"],
131
token["consumer_key"],
132
token["consumer_secret"])
133
scaclient = SoftwareCenterAgentAPI(cachedir=cachedir, auth=auth)
135
scaclient = SoftwareCenterAgentAPI(cachedir=cachedir)
140
if args.command in ("available_apps", "available_apps_qa"):
141
kwargs = {"lang": args.lang,
142
"series": args.series,
147
if args.command == "available_apps":
149
piston_reply = scaclient.available_apps(**kwargs)
151
LOG.exception("available_apps")
154
elif args.command == "available_apps_qa":
156
piston_reply = scaclient.available_apps_qa(**kwargs)
158
LOG.exception("available_apps_qa")
160
elif args.command == "subscriptions_for_me":
162
piston_reply = scaclient.subscriptions_for_me(complete_only=True)
163
# the new piston API send the data in a nasty format, most
164
# interessting stuff is in the "application" dict, move it
165
# back int othe main object here so that the parser understands it
166
for item in piston_reply:
167
for k, v in item.application.iteritems():
170
LOG.exception("subscriptions_for_me")
172
if args.command == "exhibits":
174
piston_reply = scaclient.exhibits(lang=args.lang, series=args.series)
176
LOG.exception("exhibits")
180
LOG.debug("reply: %s" % piston_reply)
181
for item in piston_reply:
182
for var in vars(item):
183
print "%s: %s" % (var, getattr(item, var))
187
# print to stdout where its consumed by the parent
188
if piston_reply is not None:
190
print pickle.dumps(piston_reply)
192
# this can happen if the parent gets killed, no need to trigger