Opened 10 years ago
Closed 10 years ago
#12201 closed defect (fixed)
it is possible to assign ticket to closed milestone
Reported by: | Owned by: | falkb | |
---|---|---|---|
Priority: | normal | Component: | SimpleMultiProjectPlugin |
Severity: | normal | Keywords: | |
Cc: | Trac Release: | 1.0 |
Description
With multi-projects enabled, and milestones associated to projects, it is possible to set ticket's milestone to the closed one.
Attachments (0)
Change History (24)
comment:1 Changed 10 years ago by
comment:2 follow-up: 3 Changed 10 years ago by
Well, with ongoing projects that have plenty of milestones set one week apart, once milestone is marked as "completed" it is pointless to allow new tickets to set milestone to any of closed/completed milestones - the list of milestones that appears contains all of them, completed ones are not even marked in any way.
If I'm not mistaken, default Trac beahviour is to present only active milestones in drop-down list.
comment:3 follow-up: 4 Changed 10 years ago by
Replying to nenad@…:
If I'm not mistaken, default Trac beahviour is to present only active milestones in drop-down list.
That's correct. However, users with TICKET_ADMIN
will see all the milestones grouped by status: Closed, Open (by due date), Open (no due date).
comment:4 Changed 10 years ago by
Replying to rjollos:
Replying to nenad@…:
If I'm not mistaken, default Trac beahviour is to present only active milestones in drop-down list.
That's correct. However, users with
TICKET_ADMIN
will see all the milestones grouped by status: Closed, Open (by due date), Open (no due date).
With "SimpleMultiProjectPlugin" plugin activated and with newly created user that does not have "TICKET_ADMIN" permission assigned, but has access to the project itself (definied within Admin / Manage Projects / Project / Restricted To Users), it is still possible to set ticket milestone to the completed one.
User has been granted these permissions:
User Action --------------------------- test EMAIL_VIEW test FILE_VIEW test LOG_VIEW test MILESTONE_VIEW test PROJECT_SETTINGS_VIEW test REPORT_SQL_VIEW test REPORT_VIEW test ROADMAP_VIEW test SEARCH_VIEW test TAGS_MODIFY test TAGS_VIEW test TICKETLOG_VIEW test TICKET_ADD_HOURS test TICKET_APPEND test TICKET_CHGPROP test TICKET_CREATE test TICKET_EDIT_CC test TICKET_EDIT_COMMENT test TICKET_MODIFY test TICKET_VIEW test TICKET_VIEW_HOURS test TIMELINE_VIEW test WIKI_CREATE test WIKI_MODIFY test WIKI_VIEW test WORK_LOG test XML_RPC
comment:5 Changed 10 years ago by
I have very intensive development and many short milestones (up to two or tree weeks). For one year we have many milestones and is become annoying to pick correct one when creating a ticket.
comment:6 Changed 10 years ago by
Is it OK for you to hide closed milestones from the new ticket form, only? The same ticket form is used also for ticket changes but in such case I'd keep the possibility to fix a milestone or version to an old (closed) one, for cleaning up things so to speak. What do you think?
comment:7 Changed 10 years ago by
I think that it would be the best if owner of TICKET_ADMIN permission (or, even better, some other/new permission) would have possibility to change milestone to the closed one, but default (for anyone without that permission) to be not to show closed milestones neither in "create new ticket" nor in "modify existing ticket" cases.
Reasoning for this is:
- when there is a need to change milestone on a per-ticket basis (no 'batch' changes), appearence of closed milestones will again make it hard to do.
- generally speaking, I believe that it will be confusing for users that on "create new" there won't be closed milestones shown, where the same user that goes to "modify ticket" can see them.
comment:8 Changed 10 years ago by
Yes, that sounds reasonable. I'm going to fix it as you suggested. Let's see if I can find the time this week.
comment:10 Changed 10 years ago by
Could you please review the following patch? Take care on the set condition logic:
-
model.py
731 731 def execute_sql_statement(db): 732 732 cursor = db.cursor() 733 733 cursor.execute(query, [new_component, old_component]) 734 735 def is_milestone_completed(self, milestone_name): 736 db = self.env.get_db_cnx() 737 cursor = db.cursor() 738 query = """SELECT completed FROM milestone WHERE name=%s;""" 739 cursor.execute(query, [milestone_name]) 740 msCompletedDate = cursor.fetchone() 741 if msCompletedDate and msCompletedDate[0]>0: 742 return True 743 return False -
ticket.py
42 42 43 43 def post_process_request(self, req, template, data, content_type): 44 44 if data and req.path_info.startswith('/ticket'): 45 is_newticket = False 45 46 ticket = data.get('ticket', None) 46 47 if ticket: 47 48 project_name = self.__SmpModel.get_ticket_project(ticket.id) 48 49 if project_name and project_name[0]: 49 50 self.__SmpModel.check_project_permission(req, project_name[0]) 51 else: 52 is_newticket = True 50 53 51 54 if template == 'ticket.html': 52 55 all_components = model.Component.select(self.env) … … 80 83 add_script_data(req, def_version) 81 84 add_script_data(req, project_versions) 82 85 83 self._add_milestones_maps(req, data['ticket'] )86 self._add_milestones_maps(req, data['ticket'], is_newticket) 84 87 85 88 return template, data, content_type 86 89 … … 97 100 98 101 return stream 99 102 100 def _add_milestones_maps(self, req, ticket_data ):103 def _add_milestones_maps(self, req, ticket_data, is_newticket): 101 104 102 105 milestone = ticket_data.get_value_or_default('milestone') 103 106 project = ticket_data.get_value_or_default('project') … … 108 111 milestonesForProject = {} 109 112 milestonesForProject[""] = { "Please, select a project!": "" } 110 113 114 have_ticketadmin = req.perm.has_permission('TICKET_ADMIN') 115 111 116 for project in sorted(allProjects, key=itemgetter(1)): 112 117 milestones = self.__SmpModel.get_milestones_of_project(project[1]) 113 118 milestonesForProject[project[1]] = { "": "" } 114 119 for milestone in sorted(milestones, key=itemgetter(0)): 115 milestonesForProject[project[1]][milestone[0]] = milestone[0] 120 ms = milestone[0] 121 is_completed = self.__SmpModel.is_milestone_completed(ms) 122 hide_milestone = (is_newticket and is_completed) or (not is_newticket and not have_ticketadmin) 123 if not hide_milestone: 124 milestonesForProject[project[1]][ms] = ms 116 125 117 126 smp_milestonesForProject = { 'smp_milestonesForProject' : milestonesForProject } 118 127 smp_initialProjectMilestone = { 'smp_initialProjectMilestone' : initialProjectMilestone }
comment:11 Changed 10 years ago by
Status: | new → accepted |
---|
comment:12 Changed 10 years ago by
It works - TICKET_ADMIN owner can set milestone to closed when modifying existing ticket; new ticket creation offers only open milestones.
comment:13 Changed 10 years ago by
Great! I'm still thinking about the permission, I mean if TICKET_ADMIN is the right one. Stay tuned... Hints very welcome (as always). :-)
comment:14 Changed 10 years ago by
Acutally, it may be better to use other permission, as TICKET_ADMIN is already over-used; for example, TICKET_ADMIN is required to make possible to change ticket milestone, and with it you can see all closed ones, too ... In fact, in the first place problem is that TICKET_ADMIN is required for milestone change.
comment:15 Changed 10 years ago by
Actually, it's programmatically quite easy for me to introduce a new plugin permission. See admin.py around line 40:
def get_permission_actions(self): """ Permissions supported by the plugin. """ return ['PROJECT_ADMIN', 'PROJECT_SETTINGS_VIEW']
One just adds another permission here and it could be used in my patch given in comment:10, though I'm not sure if that's the right way to go.
comment:16 Changed 10 years ago by
Yes, I understand you, it would make plugin to behave differently than plain Trac.
comment:17 follow-up: 20 Changed 10 years ago by
Are you sure you need TICKET_ADMIN for milestone changes since there is T:/TracPermissions#Roadmap with all those MILESTONE_... permissions?
comment:18 Changed 10 years ago by
I also see TICKET_CHGPROP in T:/TracPermissions#TicketSystem which seems to be the smallest one allowing changes to the ticket fields.
comment:19 Changed 10 years ago by
ah forget my comment:17 since we're talking about ticket fields and not managing milestones :)
comment:20 Changed 10 years ago by
Replying to falkb:
Are you sure you need TICKET_ADMIN for milestone changes since there is T:/TracPermissions#Roadmap with all those MILESTONE_... permissions?
...
I also see TICKET_CHGPROP in T:/TracPermissions#TicketSystem which seems to be the smallest one allowing changes to the ticket fields.
Problem is within this patch itself - TICKET_CHGPROP does the job without this patch, with it TICKET_ADMIN is needed. Problem is that with this
hide_milestone = (is_newticket and is_completed) or (not is_newticket and not have_ticketadmin)
we don't take into account case when ticket is not new, milestone is open, and user has TICKET_CHGPROP permission.
comment:21 Changed 10 years ago by
I'm confused and cannot follow you anymore. Can you fix this pseudo code to let it correctly set the variable 'hide_milestone'?
if is_newticket: hide_milestone = is_completed else: nenad_case = (not completed and req.perm.has_permission('TICKET_CHGPROP')) hide_milestone = not have_ticketadmin or nenad_case
comment:22 Changed 10 years ago by
Sorry for the confusion :) I believe code may look like this:
if is_newticket: hide_milestone = is_completed else: hide_milestone = not (have_ticketadmin or (not is_completed and req.perm.has_permission('TICKET_CHGPROP')))
Why should we restrict that? Have you experienced a special problem?