comparison libervia/cli/cmd_profile.py @ 4075:47401850dec6

refactoring: rename `libervia.frontends.jp` to `libervia.cli`
author Goffi <goffi@goffi.org>
date Fri, 02 Jun 2023 14:54:26 +0200
parents libervia/frontends/jp/cmd_profile.py@26b7ed2817da
children 0d7bb4df2343
comparison
equal deleted inserted replaced
4074:26b7ed2817da 4075:47401850dec6
1 #!/usr/bin/env python3
2
3
4 # Libervia CLI
5 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org)
6
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Affero General Public License as published by
9 # the Free Software Foundation, either version 3 of the License, or
10 # (at your option) any later version.
11
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Affero General Public License for more details.
16
17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20 """This module permits to manage profiles. It can list, create, delete
21 and retrieve information about a profile."""
22
23 from libervia.cli.constants import Const as C
24 from libervia.backend.core.log import getLogger
25 from libervia.backend.core.i18n import _
26 from libervia.cli import base
27
28 log = getLogger(__name__)
29
30
31 __commands__ = ["Profile"]
32
33 PROFILE_HELP = _('The name of the profile')
34
35
36 class ProfileConnect(base.CommandBase):
37 """Dummy command to use profile_session parent, i.e. to be able to connect without doing anything else"""
38
39 def __init__(self, host):
40 # it's weird to have a command named "connect" with need_connect=False, but it can be handy to be able
41 # to launch just the session, so some paradoxes don't hurt
42 super(ProfileConnect, self).__init__(host, 'connect', need_connect=False, help=('connect a profile'))
43
44 def add_parser_options(self):
45 pass
46
47 async def start(self):
48 # connection is already managed by profile common commands
49 # so we just need to check arguments and quit
50 if not self.args.connect and not self.args.start_session:
51 self.parser.error(_("You need to use either --connect or --start-session"))
52 self.host.quit()
53
54 class ProfileDisconnect(base.CommandBase):
55
56 def __init__(self, host):
57 super(ProfileDisconnect, self).__init__(host, 'disconnect', need_connect=False, help=('disconnect a profile'))
58
59 def add_parser_options(self):
60 pass
61
62 async def start(self):
63 try:
64 await self.host.bridge.disconnect(self.args.profile)
65 except Exception as e:
66 self.disp(f"can't disconnect profile: {e}", error=True)
67 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
68 else:
69 self.host.quit()
70
71
72 class ProfileCreate(base.CommandBase):
73 def __init__(self, host):
74 super(ProfileCreate, self).__init__(
75 host, 'create', use_profile=False, help=('create a new profile'))
76
77 def add_parser_options(self):
78 self.parser.add_argument('profile', type=str, help=_('the name of the profile'))
79 self.parser.add_argument(
80 '-p', '--password', type=str, default='',
81 help=_('the password of the profile'))
82 self.parser.add_argument(
83 '-j', '--jid', type=str, help=_('the jid of the profile'))
84 self.parser.add_argument(
85 '-x', '--xmpp-password', type=str,
86 help=_(
87 'the password of the XMPP account (use profile password if not specified)'
88 ),
89 metavar='PASSWORD')
90 self.parser.add_argument(
91 '-A', '--autoconnect', choices=[C.BOOL_TRUE, C.BOOL_FALSE], nargs='?',
92 const=C.BOOL_TRUE,
93 help=_('connect this profile automatically when backend starts')
94 )
95 self.parser.add_argument(
96 '-C', '--component', default='',
97 help=_('set to component import name (entry point) if this is a component'))
98
99 async def start(self):
100 """Create a new profile"""
101 if self.args.profile in await self.host.bridge.profiles_list_get():
102 self.disp(f"Profile {self.args.profile} already exists.", error=True)
103 self.host.quit(C.EXIT_BRIDGE_ERROR)
104 try:
105 await self.host.bridge.profile_create(
106 self.args.profile, self.args.password, self.args.component)
107 except Exception as e:
108 self.disp(f"can't create profile: {e}", error=True)
109 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
110
111 try:
112 await self.host.bridge.profile_start_session(
113 self.args.password, self.args.profile)
114 except Exception as e:
115 self.disp(f"can't start profile session: {e}", error=True)
116 self.host.quit(C.EXIT_BRIDGE_ERRBACK)
117
118 if self.args.jid:
119 await self.host.bridge.param_set(
120 "JabberID", self.args.jid, "Connection", profile_key=self.args.profile)
121 xmpp_pwd = self.args.password or self.args.xmpp_password
122 if xmpp_pwd:
123 await self.host.bridge.param_set(
124 "Password", xmpp_pwd, "Connection", profile_key=self.args.profile)
125
126 if self.args.autoconnect is not None:
127 await self.host.bridge.param_set(
128 "autoconnect_backend", self.args.autoconnect, "Connection",
129 profile_key=self.args.profile)
130
131 self.disp(f'profile {self.args.profile} created successfully', 1)
132 self.host.quit()
133
134
135 class ProfileDefault(base.CommandBase):
136 def __init__(self, host):
137 super(ProfileDefault, self).__init__(
138 host, 'default', use_profile=False, help=('print default profile'))
139
140 def add_parser_options(self):
141 pass
142
143 async def start(self):
144 print(await self.host.bridge.profile_name_get('@DEFAULT@'))
145 self.host.quit()
146
147
148 class ProfileDelete(base.CommandBase):
149 def __init__(self, host):
150 super(ProfileDelete, self).__init__(host, 'delete', use_profile=False, help=('delete a profile'))
151
152 def add_parser_options(self):
153 self.parser.add_argument('profile', type=str, help=PROFILE_HELP)
154 self.parser.add_argument('-f', '--force', action='store_true', help=_('delete profile without confirmation'))
155
156 async def start(self):
157 if self.args.profile not in await self.host.bridge.profiles_list_get():
158 log.error(f"Profile {self.args.profile} doesn't exist.")
159 self.host.quit(C.EXIT_NOT_FOUND)
160 if not self.args.force:
161 message = f"Are you sure to delete profile [{self.args.profile}] ?"
162 cancel_message = "Profile deletion cancelled"
163 await self.host.confirm_or_quit(message, cancel_message)
164
165 await self.host.bridge.profile_delete_async(self.args.profile)
166 self.host.quit()
167
168
169 class ProfileInfo(base.CommandBase):
170
171 def __init__(self, host):
172 super(ProfileInfo, self).__init__(
173 host, 'info', need_connect=False, use_output=C.OUTPUT_DICT,
174 help=_('get information about a profile'))
175 self.to_show = [(_("jid"), "Connection", "JabberID"),]
176
177 def add_parser_options(self):
178 self.parser.add_argument(
179 '--show-password', action='store_true',
180 help=_('show the XMPP password IN CLEAR TEXT'))
181
182 async def start(self):
183 if self.args.show_password:
184 self.to_show.append((_("XMPP password"), "Connection", "Password"))
185 self.to_show.append((_("autoconnect (backend)"), "Connection",
186 "autoconnect_backend"))
187 data = {}
188 for label, category, name in self.to_show:
189 try:
190 value = await self.host.bridge.param_get_a_async(
191 name, category, profile_key=self.host.profile)
192 except Exception as e:
193 self.disp(f"can't get {name}/{category} param: {e}", error=True)
194 else:
195 data[label] = value
196
197 await self.output(data)
198 self.host.quit()
199
200
201 class ProfileList(base.CommandBase):
202 def __init__(self, host):
203 super(ProfileList, self).__init__(
204 host, 'list', use_profile=False, use_output='list', help=('list profiles'))
205
206 def add_parser_options(self):
207 group = self.parser.add_mutually_exclusive_group()
208 group.add_argument(
209 '-c', '--clients', action='store_true', help=_('get clients profiles only'))
210 group.add_argument(
211 '-C', '--components', action='store_true',
212 help=('get components profiles only'))
213
214 async def start(self):
215 if self.args.clients:
216 clients, components = True, False
217 elif self.args.components:
218 clients, components = False, True
219 else:
220 clients, components = True, True
221 await self.output(await self.host.bridge.profiles_list_get(clients, components))
222 self.host.quit()
223
224
225 class ProfileModify(base.CommandBase):
226
227 def __init__(self, host):
228 super(ProfileModify, self).__init__(
229 host, 'modify', need_connect=False, help=_('modify an existing profile'))
230
231 def add_parser_options(self):
232 profile_pwd_group = self.parser.add_mutually_exclusive_group()
233 profile_pwd_group.add_argument(
234 '-w', '--password', help=_('change the password of the profile'))
235 profile_pwd_group.add_argument(
236 '--disable-password', action='store_true',
237 help=_('disable profile password (dangerous!)'))
238 self.parser.add_argument('-j', '--jid', help=_('the jid of the profile'))
239 self.parser.add_argument(
240 '-x', '--xmpp-password', help=_('change the password of the XMPP account'),
241 metavar='PASSWORD')
242 self.parser.add_argument(
243 '-D', '--default', action='store_true', help=_('set as default profile'))
244 self.parser.add_argument(
245 '-A', '--autoconnect', choices=[C.BOOL_TRUE, C.BOOL_FALSE], nargs='?',
246 const=C.BOOL_TRUE,
247 help=_('connect this profile automatically when backend starts')
248 )
249
250 async def start(self):
251 if self.args.disable_password:
252 self.args.password = ''
253 if self.args.password is not None:
254 await self.host.bridge.param_set(
255 "Password", self.args.password, "General", profile_key=self.host.profile)
256 if self.args.jid is not None:
257 await self.host.bridge.param_set(
258 "JabberID", self.args.jid, "Connection", profile_key=self.host.profile)
259 if self.args.xmpp_password is not None:
260 await self.host.bridge.param_set(
261 "Password", self.args.xmpp_password, "Connection",
262 profile_key=self.host.profile)
263 if self.args.default:
264 await self.host.bridge.profile_set_default(self.host.profile)
265 if self.args.autoconnect is not None:
266 await self.host.bridge.param_set(
267 "autoconnect_backend", self.args.autoconnect, "Connection",
268 profile_key=self.host.profile)
269
270 self.host.quit()
271
272
273 class Profile(base.CommandBase):
274 subcommands = (
275 ProfileConnect, ProfileDisconnect, ProfileCreate, ProfileDefault, ProfileDelete,
276 ProfileInfo, ProfileList, ProfileModify)
277
278 def __init__(self, host):
279 super(Profile, self).__init__(
280 host, 'profile', use_profile=False, help=_('profile commands'))