1 | # -*- coding: utf-8 -*- |
---|
2 | # |
---|
3 | # FlexibleAssignTo - Extension point provider for customizing |
---|
4 | # the "Assign To" ticket field. |
---|
5 | # |
---|
6 | # Copyright (C) 2007 Robert Morris <gt4329b@pobox.com> |
---|
7 | # All rights reserved. |
---|
8 | # |
---|
9 | # This software is licensed as described in the file COPYING, which |
---|
10 | # you should have received as part of this distribution. |
---|
11 | # |
---|
12 | |
---|
13 | from trac.core import Component, implements |
---|
14 | |
---|
15 | from flexibleassignto import IValidOwnerProvider, SimpleUser, getlist |
---|
16 | |
---|
17 | # $Id: SampleValidOwnerProvider.py 2665 2007-10-17 13:08:11Z gt4329b $ |
---|
18 | __version__ = '0.5' |
---|
19 | __revision__ = "$Revision: 2665 $".replace('Revision:', '') \ |
---|
20 | .replace('$', '').strip() |
---|
21 | version = __version__ |
---|
22 | fullversion = ".".join([__version__, __revision__]) |
---|
23 | |
---|
24 | # SampleValidOwnerProvider module "constants" |
---|
25 | DEFAULT_ROLES = 'DEFAULT' |
---|
26 | |
---|
27 | DEMO_USER_STORE = {'MYDOMAIN\\jdoe': {'roles': 'DEFAULT', |
---|
28 | 'fname': 'John', |
---|
29 | 'lname': 'Doe', |
---|
30 | 'email': 'jdoe@blah.com'}, |
---|
31 | 'MYDOMAIN\\dtabor': {'roles': 'DEMOROLE3,DEMOROLE2', |
---|
32 | 'fname': 'Dan', |
---|
33 | 'lname': 'Tabor', |
---|
34 | 'email': 'dtabor@blah.com'}, |
---|
35 | 'MYDOMAIN\\jdavis': {'roles': 'DEMOROLE2', |
---|
36 | 'fname': 'Josh', |
---|
37 | 'lname': 'Davis', |
---|
38 | 'email': 'jdavis@blah.com'}, |
---|
39 | 'MYDOMAIN\\kharrigan': {'roles': 'DEMOROLE3,DEFAULT', |
---|
40 | 'fname': 'Kyle', |
---|
41 | 'lname': 'Harrigan', |
---|
42 | 'email': 'kharrigan@blah.com'} |
---|
43 | } |
---|
44 | |
---|
45 | |
---|
46 | class SampleValidOwnerProvider(Component): |
---|
47 | """ |
---|
48 | This is a demo ValidOwnerProvider implementation, to demonstrate |
---|
49 | how to build a ValidOwnerProvider for use with the FlexibleAssignTo |
---|
50 | plugin. |
---|
51 | |
---|
52 | SampleValidOwnerProvider recognizes a new custom workflow state param |
---|
53 | called "roles_allowed". The demo user store in this example is just |
---|
54 | a dictionary, specified at the module level (above) DEMO_USER_STORE. |
---|
55 | Yes, it's trivial ...but it was intended to be simple. If "roles_allowed" |
---|
56 | is not specified for a workflow state, DEFAULT_ROLES is used to determine |
---|
57 | the valid owners to display in the "assign to" dropdown for that state. |
---|
58 | """ |
---|
59 | implements(IValidOwnerProvider) |
---|
60 | |
---|
61 | def getUsers(self, next_action_obj): |
---|
62 | """ |
---|
63 | Top-level method to be called to get users. Cascade-calls |
---|
64 | specific methods as needed. |
---|
65 | """ |
---|
66 | # get workflow state params, if present -- the getlist method |
---|
67 | # provided by FlexibleAssignTo does some housekeeping for us |
---|
68 | allowedroles = getlist(next_action_obj, 'roles_allowed', |
---|
69 | keep_empty=False) |
---|
70 | if allowedroles is None: |
---|
71 | allowedroles = DEFAULT_ROLES |
---|
72 | |
---|
73 | # use a dictionary temporarily, to help ensure uniqueness by |
---|
74 | # username |
---|
75 | user_obj_dict = {} |
---|
76 | for k, v in DEMO_USER_STORE.items(): |
---|
77 | if [r for r in v['roles'].split(',') if r in allowedroles]: |
---|
78 | u = DemoSimpleUser() |
---|
79 | u.userlogin = k |
---|
80 | u.lastname = v['lname'] |
---|
81 | u.firstname = v['fname'] |
---|
82 | u.email = v['email'] |
---|
83 | # cleanUsername() also sets the username class attribute |
---|
84 | u.cleanUsername() |
---|
85 | user_obj_dict.update({u.getUsername(): u}) |
---|
86 | user_objs = user_obj_dict.values() |
---|
87 | |
---|
88 | # SimpleUser *REQUIRES* that the following attributes are set: |
---|
89 | # - username (set via .setUsername()) |
---|
90 | # - option_value (set via .setOptionValue()) |
---|
91 | # - option_display (set via .setOptionDisplay()) |
---|
92 | # Not setting these attributes will cause assertion errors. |
---|
93 | for u in user_objs: |
---|
94 | u.setOptionValue("%s" % u.getUsername()) |
---|
95 | u.setOptionDisplay("*DEMO* - %s, %s (%s)" % (u.lastname, |
---|
96 | u.firstname, |
---|
97 | u.getUsername())) |
---|
98 | # sorted by last name (see DemoSimpleUser) |
---|
99 | return sorted(user_objs) |
---|
100 | |
---|
101 | |
---|
102 | class DemoSimpleUser(SimpleUser): |
---|
103 | def cleanUsername(self): |
---|
104 | """ |
---|
105 | Returns userlogin without any domain prefix. Also sets the |
---|
106 | username class attribute. |
---|
107 | """ |
---|
108 | self.setUsername(str(self.userlogin.split('\\')[-1])) |
---|
109 | return self.getUsername() |
---|
110 | |
---|
111 | def __cmp__(self, other): |
---|
112 | """ |
---|
113 | Provides sorting by user last name, via the .lastname class |
---|
114 | attribute. |
---|
115 | """ |
---|
116 | assert self.lastname is not None |
---|
117 | assert other.lastname is not None |
---|
118 | return cmp(self.lastname, other.lastname) |
---|
119 | |
---|
120 | def __repr__(self): |
---|
121 | return "<DemoSimpleUser instance - %s>" % self.userlogin |
---|