Package omero :: Package plugins :: Module user
[hide private]
[frames] | no frames]

Source Code for Module omero.plugins.user

  1  #!/usr/bin/env python 
  2  # -*- coding: utf-8 -*- 
  3  """ 
  4     User administration plugin 
  5   
  6     Copyright 2009 Glencoe Software, Inc. All rights reserved. 
  7     Use is subject to license terms supplied in LICENSE.txt 
  8   
  9  """ 
 10   
 11  import sys 
 12   
 13  from omero.cli import UserGroupControl, CLI, ExceptionHandler 
 14  from omero.rtypes import unwrap as _ 
 15   
 16  HELP = "Support for adding and managing users" 
 17   
 18   
19 -class UserControl(UserGroupControl):
20
21 - def _configure(self, parser):
22 23 self.exc = ExceptionHandler() 24 25 parser.add_login_arguments() 26 sub = parser.sub() 27 28 add = parser.add(sub, self.add, help="Add user") 29 add.add_argument( 30 "--ignore-existing", action="store_true", default=False, 31 help="Do not fail if user already exists") 32 add.add_argument( 33 "-m", "--middlename", help="Middle name, if available") 34 add.add_argument("-e", "--email") 35 add.add_argument("-i", "--institution") 36 # Capitalized since conflict with main values 37 add.add_argument( 38 "-a", "--admin", action="store_true", 39 help="Whether the user should be an admin") 40 add.add_argument("username", help="User's login name") 41 add.add_argument("firstname", help="User's given name") 42 add.add_argument("lastname", help="User's surname name") 43 self.add_group_arguments(add, "join", "the group as an owner") 44 45 password_group = add.add_mutually_exclusive_group() 46 password_group.add_argument( 47 "-P", "--userpassword", help="Password for user") 48 password_group.add_argument( 49 "--no-password", action="store_true", default=False, 50 help="Create user with empty password") 51 52 list = parser.add(sub, self.list, help="List current users") 53 printgroup = list.add_mutually_exclusive_group() 54 printgroup.add_argument( 55 "--long", action="store_true", default=True, 56 help="Print comma-separated list of all groups (default)") 57 printgroup.add_argument( 58 "--count", action="store_true", default=False, 59 help="Print count of all groups") 60 61 sortgroup = list.add_mutually_exclusive_group() 62 sortgroup.add_argument( 63 "--sort-by-id", action="store_true", default=True, 64 help="Sort users by ID (default)") 65 sortgroup.add_argument( 66 "--sort-by-login", action="store_true", default=False, 67 help="Sort users by login") 68 sortgroup.add_argument( 69 "--sort-by-first-name", action="store_true", default=False, 70 help="Sort users by first name") 71 sortgroup.add_argument( 72 "--sort-by-last-name", action="store_true", default=False, 73 help="Sort users by last name") 74 sortgroup.add_argument( 75 "--sort-by-email", action="store_true", default=False, 76 help="Sort users by email") 77 78 password = parser.add( 79 sub, self.password, help="Set user's password") 80 password.add_argument( 81 "username", nargs="?", help="Username if not the current user") 82 83 email = parser.add( 84 sub, self.email, help="List users' email addresses") 85 email.add_argument( 86 "-n", "--names", action="store_true", default=False, 87 help="Print user names along with email addresses") 88 email.add_argument( 89 "-1", "--one", action="store_true", default=False, 90 help="Print one user per line") 91 email.add_argument( 92 "-i", "--ignore", action="store_true", default=False, 93 help="Ignore users without email addresses") 94 95 joingroup = parser.add(sub, self.joingroup, "Join one or more groups") 96 self.add_user_arguments(joingroup) 97 group = self.add_group_arguments(joingroup, "join") 98 group.add_argument( 99 "--as-owner", action="store_true", default=False, 100 help="Join the group(s) as an owner") 101 102 leavegroup = parser.add( 103 sub, self.leavegroup, "Leave one or more groups") 104 self.add_user_arguments(leavegroup) 105 group = self.add_group_arguments(leavegroup, "leave") 106 group.add_argument( 107 "--as-owner", action="store_true", default=False, 108 help="Leave the owner list of the group(s)") 109 110 for x in (email, password, list, add, joingroup, leavegroup): 111 x.add_login_arguments()
112
113 - def add_user_arguments(self, parser):
114 group = parser.add_mutually_exclusive_group() 115 group.add_argument( 116 "--id", help="ID of the user. Default to the current user") 117 group.add_argument( 118 "--name", help="Name of the user. Default to the current user")
119
120 - def add_group_arguments(self, parser, action="join", owner_desc=""):
121 group = parser.add_argument_group('Group arguments') 122 group.add_argument( 123 "group_id_or_name", metavar="group", nargs="*", 124 help="ID or name of the group(s) to %s" % action) 125 group.add_argument( 126 "--group-id", metavar="group", nargs="+", 127 help="ID of the group(s) to %s" % action) 128 group.add_argument( 129 "--group-name", metavar="group", nargs="+", 130 help="Name of the group(s) to %s" % action) 131 return group
132
133 - def format_name(self, exp):
134 record = "" 135 fn = _(exp.firstName) 136 mn = " " 137 if _(exp.middleName): 138 mn = " %s " % _(exp.middleName) 139 ln = _(exp.lastName) 140 record += "%s%s%s" % (fn, mn, ln) 141 return record
142
143 - def email(self, args):
144 c = self.ctx.conn(args) 145 a = c.sf.getAdminService() 146 147 skipped = [] 148 records = [] 149 for exp in a.lookupExperimenters(): 150 151 # Handle users without email 152 if not _(exp.email): 153 if not args.ignore: 154 skipped.append(exp) 155 continue 156 157 record = "" 158 if args.names: 159 record += '"%s"' % self.format_name(exp) 160 record += " <%s>" % _(exp.email) 161 else: 162 record += _(exp.email) 163 164 records.append(record) 165 166 if args.one: 167 for record in records: 168 self.ctx.out(record) 169 else: 170 self.ctx.out(", ".join(records)) 171 172 if skipped: 173 self.ctx.err("Missing email addresses:") 174 for s in skipped: 175 self.ctx.err(self.format_name(s))
176
177 - def password(self, args):
178 import omero 179 from omero.rtypes import rstring 180 client = self.ctx.conn(args) 181 own_name = self.ctx._event_context.userName 182 admin = client.sf.getAdminService() 183 184 # tickets 3202, 5841 185 own_pw = self._ask_for_password(" for your user (%s)" 186 % own_name, strict=False) 187 try: 188 client.sf.setSecurityPassword(own_pw) 189 self.ctx.out("Verified password.\n") 190 except omero.SecurityViolation, sv: 191 import traceback 192 self.ctx.die(456, "SecurityViolation: Bad credentials") 193 self.ctx.dbg(traceback.format_exc(sv)) 194 195 if args.username: 196 self.ctx.out("Changing password for %s" % args.username) 197 else: 198 self.ctx.out("Changing password for %s" % own_name) 199 200 pw = self._ask_for_password(" to be set") 201 pw = rstring(pw) 202 if args.username: 203 admin.changeUserPassword(args.username, pw) 204 else: 205 admin.changePassword(pw) 206 self.ctx.out("Password changed")
207
208 - def list(self, args):
209 c = self.ctx.conn(args) 210 a = c.sf.getAdminService() 211 users = a.lookupExperimenters() 212 roles = a.getSecurityRoles() 213 user_group = roles.userGroupId 214 sys_group = roles.systemGroupId 215 216 from omero.util.text import TableBuilder 217 if args.count: 218 tb = TableBuilder("id", "login", "first name", "last name", 219 "email", "active", "admin", 220 "# group memberships", "# group ownerships") 221 else: 222 tb = TableBuilder("id", "login", "first name", "last name", 223 "email", "active", "admin", "member of", 224 "owner of") 225 226 # Sort users 227 if args.sort_by_login: 228 users.sort(key=lambda x: x.omeName.val) 229 elif args.sort_by_first_name: 230 users.sort(key=lambda x: x.firstName.val) 231 elif args.sort_by_last_name: 232 users.sort(key=lambda x: x.lastName.val) 233 elif args.sort_by_email: 234 users.sort(key=lambda x: (x.email and x.email.val or "")) 235 elif args.sort_by_id: 236 users.sort(key=lambda x: x.id.val) 237 238 for user in users: 239 row = [user.id.val, user.omeName.val, user.firstName.val, 240 user.lastName.val] 241 row.append(user.email and user.email.val or "") 242 active = "" 243 admin = "" 244 member_of = [] 245 leader_of = [] 246 for x in user.copyGroupExperimenterMap(): 247 if not x: 248 continue 249 gid = x.parent.id.val 250 if user_group == gid: 251 active = "Yes" 252 elif sys_group == gid: 253 admin = "Yes" 254 elif x.owner.val: 255 leader_of.append(str(gid)) 256 else: 257 member_of.append(str(gid)) 258 259 row.append(active) 260 row.append(admin) 261 262 if member_of: 263 if args.count: 264 row.append(len(member_of)) 265 else: 266 row.append(",".join(member_of)) 267 else: 268 row.append("") 269 if leader_of: 270 if args.count: 271 row.append(len(leader_of)) 272 else: 273 row.append(",".join(leader_of)) 274 else: 275 row.append("") 276 277 tb.row(*tuple(row)) 278 self.ctx.out(str(tb.build()))
279
280 - def add(self, args):
281 email = args.email 282 login = args.username 283 first = args.firstname 284 middle = args.middlename 285 last = args.lastname 286 inst = args.institution 287 pasw = args.userpassword 288 289 import omero 290 from omero.rtypes import rstring 291 from omero_model_ExperimenterI import ExperimenterI as Exp 292 from omero_model_ExperimenterGroupI import ExperimenterGroupI as Grp 293 c = self.ctx.conn(args) 294 e = Exp() 295 e.omeName = rstring(login) 296 e.firstName = rstring(first) 297 e.lastName = rstring(last) 298 e.middleName = rstring(middle) 299 e.email = rstring(email) 300 e.institution = rstring(inst) 301 302 # Fail-fast if a non-admin runs this command 303 isAdmin = self.ctx._event_context.isAdmin 304 if not isAdmin: 305 self.ctx.die(2, "SecurityViolation: admins only!") 306 307 # Fail-fast if no-password is passed and the server does not accept 308 # empty passwords 309 configService = c.getSession().getConfigService() 310 password_required = configService.getConfigValue( 311 "omero.security.password_required").lower() 312 if args.no_password and password_required != 'false': 313 self.ctx.die(502, "Server does not allow user creation with empty" 314 " passwords") 315 316 # Check user existence 317 admin = c.getSession().getAdminService() 318 try: 319 usr = admin.lookupExperimenter(login) 320 if usr: 321 if args.ignore_existing: 322 self.ctx.out("User exists: %s (id=%s)" 323 % (login, usr.id.val)) 324 return 325 else: 326 self.ctx.die(3, "User exists: %s (id=%s)" 327 % (login, usr.id.val)) 328 except omero.ApiUsageException: 329 pass # Apparently no such user exists 330 331 groups = self.list_groups(admin, args) 332 333 roles = admin.getSecurityRoles() 334 groups.append(Grp(roles.userGroupId, False)) 335 if args.admin: 336 groups.append(Grp(roles.systemGroupId, False)) 337 338 group = groups.pop(0) 339 340 try: 341 if args.no_password: 342 id = admin.createExperimenter(e, group, groups) 343 self.ctx.out("Added user %s (id=%s) without password" 344 % (login, id)) 345 else: 346 if pasw is None: 347 pasw = self._ask_for_password(" for your new user (%s)" 348 % login, strict=True) 349 id = admin.createExperimenterWithPassword(e, rstring(pasw), 350 group, groups) 351 self.ctx.out("Added user %s (id=%s) with password" 352 % (login, id)) 353 except omero.ValidationException, ve: 354 # Possible, though unlikely after previous check 355 if self.exc.is_constraint_violation(ve): 356 self.ctx.die(66, "User already exists: %s" % login) 357 else: 358 self.ctx.die(67, "Unknown ValidationException: %s" 359 % ve.message) 360 except omero.SecurityViolation, se: 361 self.ctx.die(68, "Security violation: %s" % se.message)
362
363 - def parse_userid(self, a, args):
364 if args.id: 365 user = getattr(args, "id", None) 366 return self.find_user_by_id(a, user, fatal=True) 367 elif args.name: 368 user = getattr(args, "name", None) 369 return self.find_user_by_name(a, user, fatal=True) 370 else: 371 user = self.ctx._event_context.userName 372 return self.find_user_by_name(a, user, fatal=True)
373
374 - def list_groups(self, a, args):
375 376 # Check input arguments 377 if not args.group_id_or_name and not args.group_id \ 378 and not args.group_name: 379 self.error_no_input_group(fatal=True) 380 381 # Retrieve groups by id or name 382 group_list = [] 383 if args.group_id_or_name: 384 for group in args.group_id_or_name: 385 [gid, g] = self.find_group(a, group, fatal=False) 386 if g: 387 group_list.append(g) 388 389 if args.group_id: 390 for group_id in args.group_id: 391 [gid, g] = self.find_group_by_id(a, group_id, fatal=False) 392 if g: 393 group_list.append(g) 394 395 if args.group_name: 396 for group_name in args.group_name: 397 [gid, g] = self.find_group_by_name(a, group_name, fatal=False) 398 if g: 399 group_list.append(g) 400 401 if not group_list: 402 self.error_no_group_found(fatal=True) 403 404 return group_list
405
406 - def filter_groups(self, groups, uid, owner=False, join=True):
407 408 for group in list(groups): 409 if owner: 410 uid_list = self.getownerids(group) 411 relation = "owner of" 412 else: 413 uid_list = self.getuserids(group) 414 relation = "in" 415 416 if join: 417 if uid in uid_list: 418 self.ctx.out("%s is already %s group %s" 419 % (uid, relation, group.id.val)) 420 groups.remove(group) 421 else: 422 if uid not in uid_list: 423 self.ctx.out("%s is not %s group %s" 424 % (uid, relation, group.id.val)) 425 groups.remove(group) 426 return groups
427
428 - def joingroup(self, args):
429 c = self.ctx.conn(args) 430 a = c.sf.getAdminService() 431 432 uid, username = self.parse_userid(a, args) 433 groups = self.list_groups(a, args) 434 groups = self.filter_groups(groups, uid, args.as_owner, True) 435 436 for group in groups: 437 if args.as_owner: 438 self.addownersbyid(a, group, [uid]) 439 else: 440 self.addusersbyid(a, group, [uid])
441
442 - def leavegroup(self, args):
443 c = self.ctx.conn(args) 444 a = c.sf.getAdminService() 445 446 uid, username = self.parse_userid(a, args) 447 groups = self.list_groups(a, args) 448 groups = self.filter_groups(groups, uid, args.as_owner, False) 449 450 for group in list(groups): 451 if args.as_owner: 452 self.removeownersbyid(a, group, [uid]) 453 else: 454 self.removeusersbyid(a, group, [uid])
455 try: 456 register("user", UserControl, HELP) 457 except NameError: 458 if __name__ == "__main__": 459 cli = CLI() 460 cli.register("user", UserControl, HELP) 461 cli.invoke(sys.argv[1:]) 462