View Issue Details

IDProjectCategoryView StatusLast Update
0003772mantisbtbugtrackerpublic2004-08-29 02:08
Reporterbblan Assigned Tothraxisp  
PrioritynormalSeverityfeatureReproducibilityalways
Status closedResolutionfixed 
Product Version0.18.2 
Fixed in Version0.19.0rc1 
Summary0003772: Status updating should be different from bug updating
Description

In the present version of mantis, the access level for updating a bug is managed with the g_update_bug_threshold variable. That way, a reporter can modify a bug or only the manager can (depends on the project politics).
But I think that the bug status is not part of the bug inner information and should have its own rules for updating.
Maybe the fact that access level are general is a problem too, allowing for example a DEVELOPPER to modify a REPORTER bug (if g_update_bug_threshold=REPORTER). I don't trust developpers ;-)

Additional Information

There can be a new variable g_update_bug_status_threshold that defines the access level for the bug status.
this configuration (g_update_bug_status_threshold=MANAGER and g_update_bug_threshold=REPORTER) allows all reporters to modify the bug but only the manager can modify the status.

TagsNo tags attached.
Attached Files
status.diff (23,545 bytes)   
? bug_change_status_page.php
Index: bug_actiongroup.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/bug_actiongroup.php,v
retrieving revision 1.32
diff -u -r1.32 bug_actiongroup.php
--- bug_actiongroup.php	24 Jul 2004 11:48:33 -0000	1.32
+++ bug_actiongroup.php	1 Aug 2004 23:01:48 -0000
@@ -59,7 +59,7 @@
 		case 'COPY':
 			$f_project_id = gpc_get_int( 'project_id' );
 
-			if ( access_has_project_level( config_get( 'report_bug_threshold' ), $f_project_id ) ) {
+			if ( access_has_project_level( access_get_status_threshold( NEW_ ), $f_project_id ) ) {
 				bug_copy( $t_bug_id, $f_project_id );
 			} else {
 				$t_failed_ids[] = $t_bug_id;
Index: bug_report.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/bug_report.php,v
retrieving revision 1.33
diff -u -r1.33 bug_report.php
--- bug_report.php	1 Aug 2004 22:24:58 -0000	1.33
+++ bug_report.php	1 Aug 2004 23:01:48 -0000
@@ -23,7 +23,7 @@
 	require_once( $t_core_path.'custom_field_api.php' );
 ?>
 <?php
-	access_ensure_project_level( config_get('report_bug_threshold' ) );
+	access_ensure_project_level( config_get( 'report_bug_threshold' ) );
 
 	$f_build				= gpc_get_string( 'build', '' );
 	$f_platform				= gpc_get_string( 'platform', '' );
Index: bug_update_advanced_page.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/bug_update_advanced_page.php,v
retrieving revision 1.73
diff -u -r1.73 bug_update_advanced_page.php
--- bug_update_advanced_page.php	25 Jul 2004 21:09:38 -0000	1.73
+++ bug_update_advanced_page.php	1 Aug 2004 23:01:48 -0000
@@ -220,9 +220,7 @@
 		<?php echo lang_get( 'status' ) ?>
 	</td>
 	<td bgcolor="<?php echo get_status_color( $t_bug->status ) ?>">
-		<select name="status">
-			<?php print_enum_string_option_list_workflow( 'status', $t_bug->status ) ?>
-		</select>
+		<?php print_status_option_list( 'status', $t_bug->status ) ?>
 	</td>
 
 	<?php
Index: bug_update_page.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/bug_update_page.php,v
retrieving revision 1.77
diff -u -r1.77 bug_update_page.php
--- bug_update_page.php	26 Jul 2004 13:24:38 -0000	1.77
+++ bug_update_page.php	1 Aug 2004 23:01:48 -0000
@@ -218,9 +218,7 @@
 		<?php echo lang_get( 'status' ) ?>
 	</td>
 	<td bgcolor="<?php echo get_status_color( $t_bug->status ) ?>">
-		<select name="status">
-			<?php print_enum_string_option_list_workflow( 'status', $t_bug->status ) ?>
-		</select>
+		<?php print_status_option_list( 'status', $t_bug->status ) ?>
 	</td>
 
 	<?php
Index: config_defaults_inc.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/config_defaults_inc.php,v
retrieving revision 1.188
diff -u -r1.188 config_defaults_inc.php
--- config_defaults_inc.php	1 Aug 2004 22:24:58 -0000	1.188
+++ config_defaults_inc.php	1 Aug 2004 23:01:49 -0000
@@ -735,15 +735,17 @@
 	# access level needed to report a bug
 	$g_report_bug_threshold			= REPORTER;
 
-	# access level needed to update bugs
+	# access level needed to update bugs (i.e., the update_bug_page)
 	$g_update_bug_threshold			= UPDATER;
 
 	# access level needed to re-open bugs
 	# Look in the constant_inc.php file if you want to set a different value
+	#  depricated see $g_set_status_threshold
 	$g_reopen_bug_threshold			= DEVELOPER;
 
 	# access level needed to close bugs
 	# Look in the constant_inc.php file if you want to set a different value
+	#  depricated see $g_set_status_threshold
 	$g_close_bug_threshold			= DEVELOPER;
 
 	# access level needed to monitor bugs
@@ -858,6 +860,19 @@
 	# threshold for viewing changelog
 	$g_view_changelog_threshold = VIEWER;
 
+	# status change thresholds
+	# this array sets the access thresholds needed to enter each status listed.
+	# if a status is not listed, it falls back to $g_update_bug_status_threshold
+	$g_update_bug_status_threshold = DEVELOPER;
+
+	$g_set_status_threshold[NEW_] = DEVELOPER;  # replaces $g_bug_reopen_threshold
+	# $g_set_status_threshold[ACKNOWLEDGED] = REPORTER;  
+	# $g_set_status_threshold[CONFIRMED] = REPORTER;  
+	# $g_set_status_threshold[ASSIGNED] = REPORTER;  
+	# $g_set_status_threshold[RESOLVED] = REPORTER;  
+	$g_set_status_threshold[CLOSED] = DEVELOPER;  # replaces $g_close_bug_threshold
+	
+
 	# --- login method ----------------
 	# CRYPT or PLAIN or MD5 or LDAP or BASIC_AUTH
 	# You can simply change this at will. Mantis will try to figure out how the passwords were encrypted.
@@ -1052,6 +1067,7 @@
 	$g_severity_enum_string				= '10:feature,20:trivial,30:text,40:tweak,50:minor,60:major,70:crash,80:block';
 	$g_reproducibility_enum_string		= '10:always,30:sometimes,50:random,70:have not tried,90:unable to duplicate,100:N/A';
 	$g_status_enum_string				= '10:new,20:feedback,30:acknowledged,40:confirmed,50:assigned,80:resolved,90:closed';
+	$g_status_label_enum_string = '10:new,20:feedback,30:acknowledge,40:confirm,50:assign,80:resolve,90:close';
 	$g_resolution_enum_string			= '10:open,20:fixed,30:reopened,40:unable to duplicate,50:not fixable,60:duplicate,70:not a bug,80:suspended,90:wont fix';
 	$g_projection_enum_string			= '10:none,30:tweak,50:minor fix,70:major rework,90:redesign';
 	$g_eta_enum_string					= '10:none,20:< 1 day,30:2-3 days,40:< 1 week,50:< 1 month,60:> 1 month';
Index: core/access_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/access_api.php,v
retrieving revision 1.30
diff -u -r1.30 access_api.php
--- core/access_api.php	27 Jul 2004 14:24:57 -0000	1.30
+++ core/access_api.php	1 Aug 2004 23:01:49 -0000
@@ -128,17 +128,11 @@
 	#===================================
 
 	# --------------------
-	# Check the current user's access against the given value and return true
-	#  if the user's access is equal to or higher, false otherwise.
+	# Get the current user's access
 	#
 	# This function only checks the user's global access level, ignoring any
 	#  overrides they might have at a project level
-	function access_has_global_level( $p_access_level, $p_user_id = null ) {
-		# Short circuit the check in this case
-		if ( NOBODY == $p_access_level ) {
-			return false;
-		}
-
+	function access_get_global_level( $p_user_id = null ) {
 		if ( $p_user_id === null ) {
 		    $p_user_id = auth_get_current_user_id();
 		}
@@ -150,7 +144,24 @@
 			return false;
 		}
 
-		$t_access_level = user_get_field( $p_user_id, 'access_level' );
+		return user_get_field( $p_user_id, 'access_level' );
+	}
+
+	# --------------------
+	# Check the current user's access against the given value and return true
+	#  if the user's access is equal to or higher, false otherwise.
+	#
+	function access_has_global_level( $p_access_level, $p_user_id = null ) {
+		# Short circuit the check in this case
+		if ( NOBODY == $p_access_level ) {
+			return false;
+		}
+
+		if ( $p_user_id === null ) {
+		    $p_user_id = auth_get_current_user_id();
+		}
+
+		$t_access_level = access_get_global_level( $p_user_id );
 
 		return ( $t_access_level >= $p_access_level );
 	}
@@ -165,23 +176,17 @@
 	}
 
 	# --------------------
-	# Check the current user's access against the given value and return true
-	#  if the user's access is equal to or higher, false otherwise.
+	# Get the current user's access level
 	#
 	# This function checks the project access level first (for the current project
 	#  if none is specified) and if the user is not listed, it falls back on the
 	#  user's global access level.
-	function access_has_project_level( $p_access_level, $p_project_id = null, $p_user_id = null ) {
-		# Short circuit the check in this case
-		if ( NOBODY == $p_access_level ) {
-			return false;
-		}
-
+	function access_get_project_level( $p_project_id = null, $p_user_id = null ) {
 		# Deal with not logged in silently in this case
 		# @@@ we may be able to remove this and just error
 		#     and once we default to anon login, we can remove it for sure
 		if ( !auth_is_user_authenticated() ) {
-			return false;
+			return ANYBODY;
 		}
 
 		if ( null === $p_user_id ) {
@@ -193,11 +198,11 @@
 		}
 
 		if ( ALL_PROJECTS == $p_project_id ) {
-			return access_has_global_level( $p_access_level, $p_user_id );
+			$t_access_level = access_get_global_level( $p_user_id );
+		}else{
+			$t_access_level = access_get_local_level( $p_user_id, $p_project_id );
 		}
 
-		$t_access_level = access_get_local_level( $p_user_id, $p_project_id );
-
 		# Try to use the project access level.
 		# If the user is not listed in the project, then try to fall back
 		#  to the global access level
@@ -213,6 +218,28 @@
 			}
 		}
 
+		return $t_access_level;
+	}
+
+	# --------------------
+	# Check the current user's access against the given value and return true
+	#  if the user's access is equal to or higher, false otherwise.
+	#
+	function access_has_project_level( $p_access_level, $p_project_id = null, $p_user_id = null ) {
+		# Short circuit the check in this case
+		if ( NOBODY == $p_access_level ) {
+			return false;
+		}
+
+		if ( null === $p_user_id ) {
+		    $p_user_id = auth_get_current_user_id();
+		}
+		if ( null === $p_project_id ) {
+			$p_project_id = helper_get_current_project();
+		}
+
+		$t_access_level = access_get_project_level( $p_project_id, $p_user_id );
+
 		return ( $t_access_level >= $p_access_level );
 	}
 
@@ -310,7 +337,7 @@
 			return true;
 		}
 
-		return access_has_bug_level( config_get( 'close_bug_threshold' ), $p_bug_id, $p_user_id );
+		return access_has_bug_level( access_get_status_threshold( CLOSED ), $p_bug_id, $p_user_id );
 	}
 
 	# --------------------
@@ -352,6 +379,8 @@
 	# Data Access
 	#===================================
 
+	# get the user's access level specific to this project. 
+	# return false (0) if the user has no access override here
 	function access_get_local_level( $p_user_id, $p_project_id ) {
 		$p_project_id = (int)$p_project_id; # 000001 is different from 1.
 
@@ -363,4 +392,21 @@
 			return false;
 		}
 	}
+
+	# --------------------
+	# get the access level required to change the issue to the new status
+	#  If there is no specific differentiated access level, use the 
+	#  generic update_bug_status_threshold
+	function access_get_status_threshold( $p_status, $p_project_id=ALL_PROJECTS ) {
+		
+		$t_default_level = config_get( 'update_bug_status_threshold' );
+		$t_thresh_array = config_get( 'set_status_threshold' );
+		if ( isset( $t_thresh_array[ $p_status ] ) ) {
+			return $t_thresh_array[ $p_status ];
+		}else{
+			return $t_default_level;
+		}
+	}
+
+			
 ?>
\ No newline at end of file
Index: core/filter_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/filter_api.php,v
retrieving revision 1.53
diff -u -r1.53 filter_api.php
--- core/filter_api.php	31 Jul 2004 13:16:38 -0000	1.53
+++ core/filter_api.php	1 Aug 2004 23:01:50 -0000
@@ -46,7 +46,7 @@
 		$t_project_table		= config_get( 'mantis_project_table' );
 		$t_bug_monitor_table	= config_get( 'mantis_bug_monitor_table' );
 		$t_limit_reporters		= config_get( 'limit_reporters' );
-		$t_report_bug_threshold		= config_get( 'report_bug_threshold' );
+		$t_report_bug_threshold		= access_get_status_threshold( NEW_ );
 
 		if ( $custom_filter == null ) {
 			$t_filter = current_user_get_bug_filter();
@@ -119,7 +119,7 @@
 			foreach( $t_filter['reporter_id'] as $t_filter_member ) {
 				$c_reporter_id = db_prepare_int( $t_filter_member );
 				if ( META_FILTER_MYSELF == $c_reporter_id ) {
-					if ( access_has_project_level( config_get( 'report_bug_threshold' ) ) ) {
+					if ( access_has_project_level( access_get_status_threshold( NEW_ ) ) ) {
 						$c_reporter_id = auth_get_current_user_id();
 						array_push( $t_clauses, "($t_bug_table.reporter_id='$c_reporter_id')" );
 					}
@@ -741,7 +741,7 @@
 										if ( ( $t_current == 0 ) || ( is_blank( $t_current ) ) ) {
 											$t_any_found = true;
 										} else if ( META_FILTER_MYSELF == $t_current ) {
-											if ( access_has_project_level( config_get( 'report_bug_threshold' ) ) ) {
+											if ( access_has_project_level( access_get_status_threshold( NEW_ ) ) ) {
 												$t_this_name = '[' . lang_get( 'myself' ) . ']';
 											} else {
 												$t_any_found = true;
Index: core/html_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/html_api.php,v
retrieving revision 1.115
diff -u -r1.115 html_api.php
--- core/html_api.php	1 Aug 2004 08:56:38 -0000	1.115
+++ core/html_api.php	1 Aug 2004 23:01:51 -0000
@@ -249,7 +249,6 @@
 		$t_access_level	= get_enum_element( 'access_levels', current_user_get_access_level() );
 		$t_now			= date( config_get( 'complete_date_format' ) );
 		$t_realname = current_user_get_field( 'realname' );
-
 		PRINT '<table class="hide">';
 		PRINT '<tr>';
 			PRINT '<td class="login-info-left">';
@@ -405,7 +404,7 @@
 				$t_menu_options[] = '<a href="view_all_bug_page.php">' . lang_get( 'view_bugs_link' ) . '</a>';
 
 				# Report Bugs
-				if ( access_has_project_level( REPORTER ) ) {
+				if ( access_has_project_level( config_get( 'report_bug_threshold' ) ) ) {
 					$t_menu_options[] = string_get_bug_report_link();
 				}
 
@@ -679,6 +678,59 @@
 		}
 	}
 
+  # --------------------
+  # Print Change Status to: button
+  #  This code is similar to print_status_option_list except
+  #   there is no masking, except for the current state
+  
+  function html_button_bug_change_status( $p_bug_id ) {
+		$t_bug_project_id = bug_get_field( $p_bug_id, 'project_id' );
+		$t_bug_current_state = bug_get_field( $p_bug_id, 'status' );
+		$t_current_access = access_get_project_level( $t_bug_project_id );
+		
+		$t_enum_status = config_get( 'status_enum_string'); 
+		$t_enum_workflow = config_get( 'status_enum_workflow' );
+		if ( count( $t_enum_workflow ) < 1 ) {
+			# workflow not defined, use default enum
+			$t_arr  = explode_enum_string( $t_enum_status );
+		} else {
+			# workflow defined - find allowed states
+			$t_arr  = explode_enum_string( $t_enum_workflow[$t_bug_current_state] );
+		}
+
+		$t_enum_count = count( $t_arr );
+		$t_enum_list = array();
+		for ( $i = 0; $i < $t_enum_count; $i++ ) {
+			$t_elem  = explode_enum_arr( $t_arr[$i] );
+			$t_elem2 = get_enum_element( 'status', $t_elem[0] );
+			$t_status = $t_elem[0];
+			if ( ( $t_status <> $t_bug_current_state ) && ( $t_current_access >= access_get_status_threshold( $t_status ) ) ) {
+				$t_enum_list[$t_status] = $t_elem2;
+			}
+		} # end for
+
+		if ( count( $t_enum_list ) > 0 ) {
+			echo "&nbsp;<form method=\"post\" action=\"bug_change_status_page.php\">\n";
+
+			$t_button_text = lang_get( 'bug_status_to_button' );
+			echo "	<input type=\"submit\" class=\"button\" value=\"$t_button_text\" />\n";
+
+			echo "<select name=\"new_status\">";
+			foreach ( $t_enum_list as $key => $val ) {
+				echo "<option value=\"$key\"";
+				check_selected( $val, $p_val );
+				echo ">$val</option>";
+			}
+			echo '</select>';
+
+			$t_bug_id = string_attribute( $p_bug_id );
+			echo "	<input type=\"hidden\" name=\"bug_id\" value=\"$t_bug_id\" />\n";
+
+			echo "</form>&nbsp;\n";
+		}
+
+	}
+
 	# --------------------
 	# Print Assign To: combo box of possible handlers
 	function html_button_bug_assign_to( $p_bug_id ) {
@@ -708,7 +760,7 @@
 			$t_default_assign_to = $t_current_user_id;
 		}
 
-		if ( ( $t_handler_id != $t_reporter_id ) &&
+		if ( ( $t_handler_id != $t_reporter_id ) && user_exists( $t_reporter_id ) &&
 			( access_has_bug_level( config_get( 'handle_bug_threshold' ), $p_bug_id, $t_reporter_id ) ) ) {
 		    $t_options[] = array( $t_reporter_id, '[' . lang_get( 'reporter' ) . ']' );
 
@@ -717,7 +769,7 @@
 			}
 		}
 
-		PRINT "<form method=\"post\" action=\"bug_assign.php\">\n";
+		PRINT "&nbsp;<form method=\"post\" action=\"bug_assign.php\">\n";
 
 		$t_button_text = lang_get( 'bug_assign_to_button' );
 		PRINT "	<input type=\"submit\" class=\"button\" value=\"$t_button_text\" />\n";
@@ -759,7 +811,7 @@
 		$t_bug_id = string_attribute( $p_bug_id );
 		PRINT "	<input type=\"hidden\" name=\"bug_id\" value=\"$t_bug_id\" />\n";
 
-		PRINT "</form>\n";
+		PRINT "</form>&nbsp;\n";
 	}
 
 	# --------------------
@@ -814,9 +866,10 @@
 	 		  ( ON == config_get( 'allow_reporter_reopen' ) ) 
 			 	) )
 			 ) {
-			html_button( 'bug_reopen_page.php',
+			html_button( 'bug_change_status_page.php',
 						 lang_get( 'reopen_bug_button' ),
-						 array( 'bug_id' => $p_bug_id ) );
+						 array( 'bug_id' => $p_bug_id ,
+						 				'new_status' => config_get( 'bug_reopen_status' ) ) );
 		}
 	}
 
@@ -869,8 +922,9 @@
 		$t_resolved = config_get( 'bug_resolved_status_threshold' );
 		$t_status = bug_get_field( $p_bug_id, 'status' );
 
-		PRINT '<table><tr><td>';
+		PRINT '<table><tr>';
 		if ( !bug_is_readonly( $p_bug_id ) ) {
+			PRINT '<td>';
 			# UPDATE button
 			html_button_bug_update( $p_bug_id );
 
@@ -881,28 +935,28 @@
 
 			PRINT '</td><td>';
 
-			# RESOLVE button
-			html_button_bug_resolve( $p_bug_id );
-
-			PRINT '</td><td>';
 
 			# MOVE button
 			html_button_bug_move( $p_bug_id );
 
-			# # CREATE CHILD button
+			# CREATE CHILD button
 			# PRINT '</td><td>';
 			# html_button_bug_create_child( $p_bug_id );
+		 
+			PRINT '</td>';
 		} else {
+			PRINT '<td>';
 			# REOPEN button
 			html_button_bug_reopen( $p_bug_id );
+			PRINT '</td>';
 		}
-		PRINT '</td>';
 
-		# CLOSE button
+		
 		PRINT '<td>';
-		html_button_bug_close( $p_bug_id );
+		# Change State button
+		html_button_bug_change_status( $p_bug_id );
 		PRINT '</td>';
-
+		
 		# MONITOR/UNMONITOR button
 		PRINT '<td>';
 		if ( !current_user_is_anonymous() ) {
Index: core/obsolete.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/obsolete.php,v
retrieving revision 1.25
diff -u -r1.25 obsolete.php
--- core/obsolete.php	8 May 2004 23:57:21 -0000	1.25
+++ core/obsolete.php	1 Aug 2004 23:01:51 -0000
@@ -88,4 +88,10 @@
 	config_obsolete( 'show_project_in_title', '' );
 
 	config_obsolete( 'hide_closed_default', 'hide_status_default' );
+
+	config_obsolete( 'close_bug_threshold', 'set_status_threshold' );
+	config_obsolete( 'reopen_bug_threshold', 'set_status_threshold' );
+	
+	config_obsolete( 'status_pulldown_enum_mask_string', '' );
+	
 ?>
\ No newline at end of file
Index: core/print_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/print_api.php,v
retrieving revision 1.93
diff -u -r1.93 print_api.php
--- core/print_api.php	27 Jul 2004 00:59:08 -0000	1.93
+++ core/print_api.php	1 Aug 2004 23:01:52 -0000
@@ -181,7 +181,7 @@
 		}
 
 		# if current user is a reporter, and limited reports set to ON.
-		if ( ( ON == config_get( 'limit_reporters' ) ) && ( current_user_get_access_level() <= config_get( 'report_bug_threshold' ) ) ) {
+		if ( ( ON == config_get( 'limit_reporters' ) ) && ( current_user_get_access_level() <= access_get_status_threshold( NEW_ ) ) ) {
 			$t_user['id'] = auth_get_current_user_id();
 			$t_user['username'] = user_get_field( $t_user['id'], 'username' );
 			$t_user['realname'] = user_get_field( $t_user['id'], 'realname' );
@@ -587,28 +587,47 @@
 	# or the input parameter if workflows are not used
 	# $p_enum_name : name of enumeration (eg: status)
 	# $p_val : current value
-	function print_enum_string_option_list_workflow( $p_enum_name, $p_val = 0 ) {
-		$t_config_var_name = $p_enum_name . '_enum_string';
-		$t_config_var_value = config_get( $t_config_var_name );
-		$t_enum_workflow = config_get( $p_enum_name . '_enum_workflow' );
+	function print_status_option_list( $p_select_label, $p_current_value = 0 ) {
+		$t_config_var_value = config_get( 'status_enum_string'); 
+		$t_enum_workflow = config_get( 'status_enum_workflow' );
+		$t_current_auth = access_get_project_level();
 
 		if ( count( $t_enum_workflow ) < 1 ) {
 			# workflow not defined, use default enum
 			$t_arr  = explode_enum_string( $t_config_var_value );
 		} else {
 			# workflow defined - find allowed states
-			$t_arr  = explode_enum_string( $t_enum_workflow[$p_val] );
+			$t_arr  = explode_enum_string( $t_enum_workflow[$p_current_value] );
 		}
 
 		$t_enum_count = count( $t_arr );
+		$t_enum_list = array();
+		$t_current_state = '';
 
 		for ( $i = 0; $i < $t_enum_count; $i++ ) {
 			$t_elem  = explode_enum_arr( $t_arr[$i] );
-			$t_elem2 = get_enum_element( $p_enum_name, $t_elem[0] );
-			echo "<option value=\"$t_elem[0]\"";
-			check_selected( $t_elem[0], $p_val );
-			echo ">$t_elem2</option>";
+			$t_elem2 = get_enum_element( 'status', $t_elem[0] );
+			$t_status = $t_elem[0];
+			if ( $t_status == $p_current_value ) {
+				$t_current_state = $t_elem2;
+			}
+			if ( $t_current_auth >= access_get_status_threshold( $t_status ) ) {
+				$t_enum_list[$t_status] = $t_elem2;
+			}
 		} # end for
+
+		if ( count( $t_enum_list ) > 0 ) {
+			echo '<select name="' . $p_select_label . '">';
+			foreach ( $t_enum_list as $key => $val ) {
+				echo "<option value=\"$key\"";
+				check_selected( $val, $p_val );
+				echo ">$val</option>";
+			}
+			echo '</select>';
+		}else{
+			echo $t_current_state;
+		}
+
 	}
 	# --------------------
 	# prints the list of a project's users
 
Index: lang/strings_english.txt
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/lang/strings_english.txt,v
retrieving revision 1.192
diff -u -r1.192 strings_english.txt
--- lang/strings_english.txt	1 Aug 2004 22:24:59 -0000	1.192
+++ lang/strings_english.txt	1 Aug 2004 23:02:01 -0000
@@ -248,6 +248,7 @@
 $s_severity_enum_string = '10:feature,20:trivial,30:text,40:tweak,50:minor,60:major,70:crash,80:block';
 $s_reproducibility_enum_string = '10:always,30:sometimes,50:random,70:have not tried,90:unable to duplicate,100:N/A';
 $s_status_enum_string = '10:new,20:feedback,30:acknowledged,40:confirmed,50:assigned,80:resolved,90:closed';
+$s_status_label_enum_string = '10:new,20:feedback,30:acknowledge,40:confirm,50:assign,80:resolve,90:close';
 $s_resolution_enum_string = '10:open,20:fixed,30:reopened,40:unable to duplicate,50:not fixable,60:duplicate,70:not an issue,80:suspended,90:won\'t fix';
 $s_projection_enum_string = '10:none,30:tweak,50:minor fix,70:major rework,90:redesign';
 $s_eta_enum_string = '10:none,20:< 1 day,30:2-3 days,40:< 1 week,50:< 1 month,60:> 1 month';
@@ -391,6 +392,18 @@
 # bug_assign.php
 $s_bug_assign_msg = 'Issue has been successfully assigned...';
 
+# bug_change_status_page.php
+$s_new_bug_title = 'New Issue';
+$s_feedback_bug_title = 'Provide Feedback to Issue';
+$s_acknowledge_bug_title = 'Acknowledge Issue';
+$s_confirm_bug_title = 'Confirm Issue';
+$s_assign_bug_title = 'Assign Issue';
+$s_new_bug_button = 'New Issue';
+$s_feedback_bug_button = 'Provide Feedback';
+$s_acknowledge_bug_button = 'Acknowledge Issue';
+$s_confirm_bug_button = 'Confirm Issue';
+$s_assign_bug_button = 'Assign Issue';
+
 # bug_close.php
 $s_bug_close_msg = 'Issue has been closed...';
 $s_close_immediately = 'Close immediately:';
@@ -897,6 +910,7 @@
 $s_system_profile = 'System Description';
 $s_update_bug_button = 'Update Issue';
 $s_bug_assign_to_button = 'Assign To:';
+$s_bug_status_to_button = 'Change Status To:';
 $s_reopen_bug_button = 'Reopen Issue';
 $s_move_bug_button = 'Move Issue';
 $s_attached_files = 'Attached Files';
status.diff (23,545 bytes)   
status.tar.gz (62,068 bytes)
change_status.diff (20,120 bytes)   
Index: bug_update_advanced_page.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/bug_update_advanced_page.php,v
retrieving revision 1.74
diff -u -r1.74 bug_update_advanced_page.php
--- bug_update_advanced_page.php	2 Aug 2004 18:16:20 -0000	1.74
+++ bug_update_advanced_page.php	3 Aug 2004 13:16:16 -0000
@@ -220,9 +220,7 @@
 		<?php echo lang_get( 'status' ) ?>
 	</td>
 	<td bgcolor="<?php echo get_status_color( $t_bug->status ) ?>">
-		<select name="status">
-			<?php print_enum_string_option_list_workflow( 'status', $t_bug->status ) ?>
-		</select>
+		<?php print_status_option_list( 'status', $t_bug->status ) ?>
 	</td>
 
 	<?php
Index: bug_update_page.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/bug_update_page.php,v
retrieving revision 1.78
diff -u -r1.78 bug_update_page.php
--- bug_update_page.php	2 Aug 2004 18:16:20 -0000	1.78
+++ bug_update_page.php	3 Aug 2004 13:16:39 -0000
@@ -218,9 +218,7 @@
 		<?php echo lang_get( 'status' ) ?>
 	</td>
 	<td bgcolor="<?php echo get_status_color( $t_bug->status ) ?>">
-		<select name="status">
-			<?php print_enum_string_option_list_workflow( 'status', $t_bug->status ) ?>
-		</select>
+		<?php print_status_option_list( 'status', $t_bug->status ) ?>
 	</td>
 
 	<?php
Index: config_defaults_inc.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/config_defaults_inc.php,v
retrieving revision 1.188
diff -u -r1.188 config_defaults_inc.php
--- config_defaults_inc.php	1 Aug 2004 22:24:58 -0000	1.188
+++ config_defaults_inc.php	3 Aug 2004 13:07:48 -0000
@@ -735,17 +735,9 @@
 	# access level needed to report a bug
 	$g_report_bug_threshold			= REPORTER;
 
-	# access level needed to update bugs
+	# access level needed to update bugs (i.e., the update_bug_page)
 	$g_update_bug_threshold			= UPDATER;
 
-	# access level needed to re-open bugs
-	# Look in the constant_inc.php file if you want to set a different value
-	$g_reopen_bug_threshold			= DEVELOPER;
-
-	# access level needed to close bugs
-	# Look in the constant_inc.php file if you want to set a different value
-	$g_close_bug_threshold			= DEVELOPER;
-
 	# access level needed to monitor bugs
 	# Look in the constant_inc.php file if you want to set a different value
 	$g_monitor_bug_threshold		= REPORTER;
@@ -858,6 +850,14 @@
 	# threshold for viewing changelog
 	$g_view_changelog_threshold = VIEWER;
 
+	# status change thresholds
+	$g_update_bug_status_threshold = DEVELOPER;
+
+	# this array sets the access thresholds needed to enter each status listed.
+	# if a status is not listed, it falls back to $g_update_bug_status_threshold
+	# example: $g_set_status_threshold = array( ACKNOWLEDGED => MANAGER, CONFIRMED => DEVELOPER, CLOSED => MANAGER );
+	$g_set_status_threshold = array();
+	
 	# --- login method ----------------
 	# CRYPT or PLAIN or MD5 or LDAP or BASIC_AUTH
 	# You can simply change this at will. Mantis will try to figure out how the passwords were encrypted.
@@ -1284,4 +1284,4 @@
 	# Enable support for bug relationships where a bug can be a related, dependent on, or duplicate of another.
 	# See relationship_api.php for more details.
 	$g_enable_relationship = ON;
-?>
\ No newline at end of file
+?>
Index: core/access_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/access_api.php,v
retrieving revision 1.30
diff -u -r1.30 access_api.php
--- core/access_api.php	27 Jul 2004 14:24:57 -0000	1.30
+++ core/access_api.php	3 Aug 2004 13:01:27 -0000
@@ -128,17 +128,11 @@
 	#===================================
 
 	# --------------------
-	# Check the current user's access against the given value and return true
-	#  if the user's access is equal to or higher, false otherwise.
+	# Get the current user's access
 	#
 	# This function only checks the user's global access level, ignoring any
 	#  overrides they might have at a project level
-	function access_has_global_level( $p_access_level, $p_user_id = null ) {
-		# Short circuit the check in this case
-		if ( NOBODY == $p_access_level ) {
-			return false;
-		}
-
+	function access_get_global_level( $p_user_id = null ) {
 		if ( $p_user_id === null ) {
 		    $p_user_id = auth_get_current_user_id();
 		}
@@ -150,7 +144,24 @@
 			return false;
 		}
 
-		$t_access_level = user_get_field( $p_user_id, 'access_level' );
+		return user_get_field( $p_user_id, 'access_level' );
+	}
+
+	# --------------------
+	# Check the current user's access against the given value and return true
+	#  if the user's access is equal to or higher, false otherwise.
+	#
+	function access_has_global_level( $p_access_level, $p_user_id = null ) {
+		# Short circuit the check in this case
+		if ( NOBODY == $p_access_level ) {
+			return false;
+		}
+
+		if ( $p_user_id === null ) {
+		    $p_user_id = auth_get_current_user_id();
+		}
+
+		$t_access_level = access_get_global_level( $p_user_id );
 
 		return ( $t_access_level >= $p_access_level );
 	}
@@ -165,23 +176,17 @@
 	}
 
 	# --------------------
-	# Check the current user's access against the given value and return true
-	#  if the user's access is equal to or higher, false otherwise.
+	# Get the current user's access level
 	#
 	# This function checks the project access level first (for the current project
 	#  if none is specified) and if the user is not listed, it falls back on the
 	#  user's global access level.
-	function access_has_project_level( $p_access_level, $p_project_id = null, $p_user_id = null ) {
-		# Short circuit the check in this case
-		if ( NOBODY == $p_access_level ) {
-			return false;
-		}
-
+	function access_get_project_level( $p_project_id = null, $p_user_id = null ) {
 		# Deal with not logged in silently in this case
 		# @@@ we may be able to remove this and just error
 		#     and once we default to anon login, we can remove it for sure
 		if ( !auth_is_user_authenticated() ) {
-			return false;
+			return ANYBODY;
 		}
 
 		if ( null === $p_user_id ) {
@@ -193,11 +198,11 @@
 		}
 
 		if ( ALL_PROJECTS == $p_project_id ) {
-			return access_has_global_level( $p_access_level, $p_user_id );
+			$t_access_level = access_get_global_level( $p_user_id );
+		} else {
+			$t_access_level = access_get_local_level( $p_user_id, $p_project_id );
 		}
 
-		$t_access_level = access_get_local_level( $p_user_id, $p_project_id );
-
 		# Try to use the project access level.
 		# If the user is not listed in the project, then try to fall back
 		#  to the global access level
@@ -213,6 +218,28 @@
 			}
 		}
 
+		return $t_access_level;
+	}
+
+	# --------------------
+	# Check the current user's access against the given value and return true
+	#  if the user's access is equal to or higher, false otherwise.
+	#
+	function access_has_project_level( $p_access_level, $p_project_id = null, $p_user_id = null ) {
+		# Short circuit the check in this case
+		if ( NOBODY == $p_access_level ) {
+			return false;
+		}
+
+		if ( null === $p_user_id ) {
+		    $p_user_id = auth_get_current_user_id();
+		}
+		if ( null === $p_project_id ) {
+			$p_project_id = helper_get_current_project();
+		}
+
+		$t_access_level = access_get_project_level( $p_project_id, $p_user_id );
+
 		return ( $t_access_level >= $p_access_level );
 	}
 
@@ -310,7 +337,7 @@
 			return true;
 		}
 
-		return access_has_bug_level( config_get( 'close_bug_threshold' ), $p_bug_id, $p_user_id );
+		return access_has_bug_level( access_get_status_threshold( CLOSED ), $p_bug_id, $p_user_id );
 	}
 
 	# --------------------
@@ -352,6 +379,8 @@
 	# Data Access
 	#===================================
 
+	# get the user's access level specific to this project. 
+	# return false (0) if the user has no access override here
 	function access_get_local_level( $p_user_id, $p_project_id ) {
 		$p_project_id = (int)$p_project_id; # 000001 is different from 1.
 
@@ -363,4 +392,17 @@
 			return false;
 		}
 	}
-?>
\ No newline at end of file
+
+	# --------------------
+	# get the access level required to change the issue to the new status
+	#  If there is no specific differentiated access level, use the 
+	#  generic update_bug_status_threshold
+	function access_get_status_threshold( $p_status, $p_project_id = ALL_PROJECTS ) {
+		$t_thresh_array = config_get( 'set_status_threshold' );
+		if ( isset( $t_thresh_array[ $p_status ] ) ) {
+			return $t_thresh_array[$p_status];
+		} else {
+			return config_get( 'update_bug_status_threshold' );
+		}
+	}
+?>
Index: core/error_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/error_api.php,v
retrieving revision 1.31
diff -u -r1.31 error_api.php
--- core/error_api.php	1 Aug 2004 12:51:38 -0000	1.31
+++ core/error_api.php	3 Aug 2004 13:29:44 -0000
@@ -55,7 +55,7 @@
 				$t_error_type = 'SYSTEM NOTICE';
 				$t_error_description = $p_error;
 				if ( ON == config_get( 'show_notices' ) ) {
-					$t_method = 'inline';
+					$t_method = 'halt'; // 'inline';
 				}
 				break;
 			case E_USER_ERROR:
Index: core/html_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/html_api.php,v
retrieving revision 1.115
diff -u -r1.115 html_api.php
--- core/html_api.php	1 Aug 2004 08:56:38 -0000	1.115
+++ core/html_api.php	3 Aug 2004 13:32:14 -0000
@@ -405,7 +405,7 @@
 				$t_menu_options[] = '<a href="view_all_bug_page.php">' . lang_get( 'view_bugs_link' ) . '</a>';
 
 				# Report Bugs
-				if ( access_has_project_level( REPORTER ) ) {
+				if ( access_has_project_level( config_get( 'report_bug_threshold' ) ) ) {
 					$t_menu_options[] = string_get_bug_report_link();
 				}
 
@@ -680,6 +680,57 @@
 	}
 
 	# --------------------
+	# Print Change Status to: button
+	#  This code is similar to print_status_option_list except
+	#   there is no masking, except for the current state
+	function html_button_bug_change_status( $p_bug_id ) {
+		$t_bug_project_id = bug_get_field( $p_bug_id, 'project_id' );
+		$t_bug_current_state = bug_get_field( $p_bug_id, 'status' );
+		$t_current_access = access_get_project_level( $t_bug_project_id );
+		
+		$t_enum_status = config_get( 'status_enum_string'); 
+		$t_enum_workflow = config_get( 'status_enum_workflow' );
+		if ( count( $t_enum_workflow ) < 1 ) {
+			# workflow not defined, use default enum
+			$t_arr  = explode_enum_string( $t_enum_status );
+		} else {
+			# workflow defined - find allowed states
+			$t_arr  = explode_enum_string( $t_enum_workflow[$t_bug_current_state] );
+		}
+
+		$t_enum_count = count( $t_arr );
+		$t_enum_list = array();
+		for ( $i = 0; $i < $t_enum_count; $i++ ) {
+			$t_elem  = explode_enum_arr( $t_arr[$i] );
+			$t_elem2 = get_enum_element( 'status', $t_elem[0] );
+			$t_status = $t_elem[0];
+			if ( ( $t_status <> $t_bug_current_state ) && ( $t_current_access >= access_get_status_threshold( $t_status ) ) ) {
+				$t_enum_list[$t_status] = $t_elem2;
+			}
+		} # end for
+
+		if ( count( $t_enum_list ) > 0 ) {
+			echo "&nbsp;<form method=\"post\" action=\"bug_change_status_page.php\">\n";
+
+			$t_button_text = lang_get( 'bug_status_to_button' );
+			echo "	<input type=\"submit\" class=\"button\" value=\"$t_button_text\" />\n";
+
+			echo "<select name=\"new_status\">";
+			foreach ( $t_enum_list as $key => $val ) {
+				echo "<option value=\"$key\"";
+				check_selected( $val, $t_bug_current_state );  # select current status which doesn't exist, hence no selection
+				echo ">$val</option>";
+			}
+			echo '</select>';
+
+			$t_bug_id = string_attribute( $p_bug_id );
+			echo "	<input type=\"hidden\" name=\"bug_id\" value=\"$t_bug_id\" />\n";
+
+			echo "</form>&nbsp;\n";
+		}
+	}
+
+	# --------------------
 	# Print Assign To: combo box of possible handlers
 	function html_button_bug_assign_to( $p_bug_id ) {
 		# make sure status is allowed of assign would cause auto-set-status
@@ -708,7 +759,7 @@
 			$t_default_assign_to = $t_current_user_id;
 		}
 
-		if ( ( $t_handler_id != $t_reporter_id ) &&
+		if ( ( $t_handler_id != $t_reporter_id ) && user_exists( $t_reporter_id ) &&
 			( access_has_bug_level( config_get( 'handle_bug_threshold' ), $p_bug_id, $t_reporter_id ) ) ) {
 		    $t_options[] = array( $t_reporter_id, '[' . lang_get( 'reporter' ) . ']' );
 
@@ -717,7 +768,7 @@
 			}
 		}
 
-		PRINT "<form method=\"post\" action=\"bug_assign.php\">\n";
+		PRINT "&nbsp;<form method=\"post\" action=\"bug_assign.php\">\n";
 
 		$t_button_text = lang_get( 'bug_assign_to_button' );
 		PRINT "	<input type=\"submit\" class=\"button\" value=\"$t_button_text\" />\n";
@@ -759,7 +810,7 @@
 		$t_bug_id = string_attribute( $p_bug_id );
 		PRINT "	<input type=\"hidden\" name=\"bug_id\" value=\"$t_bug_id\" />\n";
 
-		PRINT "</form>\n";
+		PRINT "</form>&nbsp;\n";
 	}
 
 	# --------------------
@@ -814,9 +865,10 @@
 	 		  ( ON == config_get( 'allow_reporter_reopen' ) ) 
 			 	) )
 			 ) {
-			html_button( 'bug_reopen_page.php',
+			html_button( 'bug_change_status_page.php',
 						 lang_get( 'reopen_bug_button' ),
-						 array( 'bug_id' => $p_bug_id ) );
+						 array( 'bug_id' => $p_bug_id ,
+						 				'new_status' => config_get( 'bug_reopen_status' ) ) );
 		}
 	}
 
@@ -869,8 +921,9 @@
 		$t_resolved = config_get( 'bug_resolved_status_threshold' );
 		$t_status = bug_get_field( $p_bug_id, 'status' );
 
-		PRINT '<table><tr><td>';
+		PRINT '<table><tr>';
 		if ( !bug_is_readonly( $p_bug_id ) ) {
+			PRINT '<td>';
 			# UPDATE button
 			html_button_bug_update( $p_bug_id );
 
@@ -881,26 +934,24 @@
 
 			PRINT '</td><td>';
 
-			# RESOLVE button
-			html_button_bug_resolve( $p_bug_id );
-
-			PRINT '</td><td>';
-
 			# MOVE button
 			html_button_bug_move( $p_bug_id );
 
 			# # CREATE CHILD button
 			# PRINT '</td><td>';
 			# html_button_bug_create_child( $p_bug_id );
+		 
+			PRINT '</td>';
 		} else {
+			PRINT '<td>';
 			# REOPEN button
 			html_button_bug_reopen( $p_bug_id );
+			PRINT '</td>';
 		}
-		PRINT '</td>';
-
-		# CLOSE button
+		
 		PRINT '<td>';
-		html_button_bug_close( $p_bug_id );
+		# Change State button
+		html_button_bug_change_status( $p_bug_id );
 		PRINT '</td>';
 
 		# MONITOR/UNMONITOR button
@@ -919,4 +970,4 @@
 		html_button_bug_delete( $p_bug_id );
 		PRINT '</td></tr></table>';
 	}
-?>
\ No newline at end of file
+?>
Index: core/obsolete.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/obsolete.php,v
retrieving revision 1.25
diff -u -r1.25 obsolete.php
--- core/obsolete.php	8 May 2004 23:57:21 -0000	1.25
+++ core/obsolete.php	3 Aug 2004 13:01:57 -0000
@@ -88,4 +88,10 @@
 	config_obsolete( 'show_project_in_title', '' );
 
 	config_obsolete( 'hide_closed_default', 'hide_status_default' );
-?>
\ No newline at end of file
+
+	config_obsolete( 'close_bug_threshold', 'set_status_threshold' );
+	config_obsolete( 'reopen_bug_threshold', 'set_status_threshold' );
+	
+	config_obsolete( 'status_pulldown_enum_mask_string', '' );
+	
+?>
Index: core/print_api.php
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/core/print_api.php,v
retrieving revision 1.93
diff -u -r1.93 print_api.php
--- core/print_api.php	27 Jul 2004 00:59:08 -0000	1.93
+++ core/print_api.php	3 Aug 2004 13:23:57 -0000
@@ -586,29 +586,48 @@
 	# Select the proper enum values for status based on workflow
 	# or the input parameter if workflows are not used
 	# $p_enum_name : name of enumeration (eg: status)
-	# $p_val : current value
-	function print_enum_string_option_list_workflow( $p_enum_name, $p_val = 0 ) {
-		$t_config_var_name = $p_enum_name . '_enum_string';
-		$t_config_var_value = config_get( $t_config_var_name );
-		$t_enum_workflow = config_get( $p_enum_name . '_enum_workflow' );
+	# $p_current_value : current value
+	function print_status_option_list( $p_select_label, $p_current_value = 0 ) {
+		$t_config_var_value = config_get( 'status_enum_string' );
+		$t_enum_workflow = config_get( 'status_enum_workflow' );
+		$t_current_auth = access_get_project_level();
 
 		if ( count( $t_enum_workflow ) < 1 ) {
 			# workflow not defined, use default enum
 			$t_arr  = explode_enum_string( $t_config_var_value );
 		} else {
 			# workflow defined - find allowed states
-			$t_arr  = explode_enum_string( $t_enum_workflow[$p_val] );
+			$t_arr  = explode_enum_string( $t_enum_workflow[$p_current_value] );
 		}
 
 		$t_enum_count = count( $t_arr );
+		$t_enum_list = array();
+		$t_current_state = '';
 
 		for ( $i = 0; $i < $t_enum_count; $i++ ) {
 			$t_elem  = explode_enum_arr( $t_arr[$i] );
-			$t_elem2 = get_enum_element( $p_enum_name, $t_elem[0] );
-			echo "<option value=\"$t_elem[0]\"";
-			check_selected( $t_elem[0], $p_val );
-			echo ">$t_elem2</option>";
+			$t_elem2 = get_enum_element( 'status', $t_elem[0] );
+			$t_status = $t_elem[0];
+			if ( $t_status == $p_current_value ) {
+				$t_current_state = $t_elem2;
+			}
+			if ( $t_current_auth >= access_get_status_threshold( $t_status ) ) {
+				$t_enum_list[$t_status] = $t_elem2;
+			}
 		} # end for
+
+		if ( count( $t_enum_list ) > 0 ) {
+			echo '<select name="' . $p_select_label . '">';
+			foreach ( $t_enum_list as $key => $val ) {
+				echo "<option value=\"$key\"";
+				check_selected( $val, $p_current_value );
+				echo ">$val</option>";
+			}
+			echo '</select>';
+		} else {
+			echo $t_current_state;
+		}
+
 	}
 	# --------------------
 	# prints the list of a project's users
Index: lang/strings_english.txt
===================================================================
RCS file: /cvsroot/mantisbt/mantisbt/lang/strings_english.txt,v
retrieving revision 1.193
diff -u -r1.193 strings_english.txt
--- lang/strings_english.txt	2 Aug 2004 18:17:59 -0000	1.193
+++ lang/strings_english.txt	3 Aug 2004 13:33:38 -0000
@@ -391,12 +391,24 @@
 # bug_assign.php
 $s_bug_assign_msg = 'Issue has been successfully assigned...';
 
+# bug_change_status_page.php
+$s_new_bug_title = 'New Issue';
+$s_feedback_bug_title = 'Provide Feedback to Issue';
+$s_acknowledged_bug_title = 'Acknowledge Issue';
+$s_confirmed_bug_title = 'Confirm Issue';
+$s_assigned_bug_title = 'Assign Issue';
+$s_new_bug_button = 'New Issue';
+$s_feedback_bug_button = 'Provide Feedback';
+$s_acknowledged_bug_button = 'Acknowledge Issue';
+$s_confirmed_bug_button = 'Confirm Issue';
+$s_assigned_bug_button = 'Assign Issue';
+
 # bug_close.php
 $s_bug_close_msg = 'Issue has been closed...';
 $s_close_immediately = 'Close immediately:';
 
 # bug_close_page.php
-$s_close_bug_title = 'Close Issue';
+$s_closed_bug_title = 'Close Issue';
 
 # bug_delete.php
 $s_bug_deleted_msg = 'Issue has been deleted...';
@@ -424,8 +436,8 @@
 $s_bugnote_add_reopen_button = 'Add Note and Reopen Issue';
 
 # bug_resolve_page.php
-$s_resolve_bug_title = 'Resolve Issue';
-$s_resolve_bug_button = 'Resolve Issue';
+$s_resolved_bug_title = 'Resolve Issue';
+$s_resolved_bug_button = 'Resolve Issue';
 
 # bug_resolve_page2.php
 $s_bug_resolved_msg = 'Issue has been resolved. Enter note below...';
@@ -897,6 +909,7 @@
 $s_system_profile = 'System Description';
 $s_update_bug_button = 'Update Issue';
 $s_bug_assign_to_button = 'Assign To:';
+$s_bug_status_to_button = 'Change Status To:';
 $s_reopen_bug_button = 'Reopen Issue';
 $s_move_bug_button = 'Move Issue';
 $s_attached_files = 'Attached Files';
@@ -1007,4 +1020,4 @@
 
 # Source Control Integration
 $s_checkin = 'Checkin';
-?>
\ No newline at end of file
+?>
change_status.diff (20,120 bytes)   

Relationships

has duplicate 0004131 closedthraxisp Closing bugs when you're not allowed to. 
has duplicate 0003381 closedvboctor Users with out rights can close issues 
has duplicate 0004352 closedthraxisp Resolve button should have own access rights 
related to 0003771 closedthraxisp Status pulldown on Update pages should not always show full list 
related to 0003970 closedthraxisp Reopen issue logic was broken for ustom reopen statuses 
related to 0003766 closedthraxisp status notifications are confused and confusing 

Activities

permutations

permutations

2004-04-27 16:06

reporter   ~0005445

I agree that too much access is given on this page and there needs to be finer filtering.

Also, thresholds set elsewhere are ignored here. For example, in our installation, only managers can close a report, but "close" is still listed on the Update menu. I had to take it off with a hack.

thraxisp

thraxisp

2004-07-19 12:00

reporter   ~0006147

I think that this can be done within the existing users and thresholds. There is another threshold that allows the addition of bug notes (add_bugnote_threshold), which is the way I assume that people would provide input on the issue. If you then set the update_bug_threshold to MANAGER, only they can update the status. The update button will only show up for managers.

Is this sufficient?

permutations: I'm resolving this under 0004131.

RJelinek

RJelinek

2004-07-19 14:39

reporter   ~0006150

I have the same requirement as Benoit Blancart (from a different point of view).

I would like to have testers, who should be able to update the status, but they should not be allowed to update the fields of the issue.

vboctor

vboctor

2004-07-19 16:33

manager   ~0006151

Option 1:
Have a threshold to change status, if the current user doesn't have this threshold, then the update page will just show the status rather than allowing editing of it.

Option 2:

This is just a thought which needs some refining before it becomes useful.

Adding a button similar to the Assign To button on the view pages. The button is to be called "Status" and followed with a combo-box which includes all statuses (that comply with the workflow based on the current status). This should replace the "Resolve", "Close" buttons.

Status: New, Feedback, Assigned, Resolved, Closed

We can even think of a way where the user can specify whether just to change the status or open the details page which allows addition of bugnotes, or in resolve also allows for setting of resolution, fixed in version, ...etc. For example,

Status: New, Feedback, Assigned, Resolved, Closed, New, Feedback, ...

thraxisp

thraxisp

2004-07-19 18:37

reporter   ~0006159

I like both options as they are sort of orthogonal.

There is also an interaction with three other config variables: update_bug_threshold, reopen_bug_threshold, and close_bug_threshold. These basically control who can update the bug status. It also controls whether the buttons show up to get to the "update" page.

I think that we can live with the existing set of variables. The addition is to make sure that the list in the update page obeys the priviledge rules.

vboctor

vboctor

2004-07-19 20:18

manager   ~0006162

Sorry, I forgot to mention that the appearance of the button in option 2 will be controlled the same way like the other buttons via a threshold. So option 2 basically includes option 1.

It may be time to consider adding the following configuration:

$g_set_status_threshold = array( _NEW => UPDATER, ACKNOWLEDGED => DEVELOPER, CONFIRMED => DEVELOPER, ASSIGNED => DEVELOPER, RESOLVED => DEVELOPER, CLOSED => MANAGER );

This will replace thresholds likse close_bug_threshold, but it will not replace thresholds like re-open issue threshold, to replace everything, we probably need to have a threshold associated with each transition:

_NEW -> ACKNOWLEDGED requires X
ACKNOWLEDGED -> _NEW requires Y

This will be too complicated. Probably somewhere in the middle would be nice. Maybe we can even integrate it as part of the workflow definition. The workflow currently lists all the possible transitions from each state, we may have it list the transitions + required access level.

Anyway, these are some thoughts... Have to go now.

bblan

bblan

2004-07-20 03:47

reporter   ~0006167

I like the option 2 because it can help in the mantis workflow implementation.
The combo box lists all the available statuses from the current status and for the current user (an anonymous should not have the right to change any status for example). And when you edit the bug, the status is not editable except with special right and without workflow rules (a manager forcing a status for example).

The best for this workflow to work is to get rid of explicit status in the code of mantis. That means that there should not be buttons like "close" or "resolve" but only the combo box.

thraxisp

thraxisp

2004-07-20 14:26

reporter   ~0006178

Option 2 would leave the following buttons on the bottom of the page:

"Update Issue" - change the information about the base issue (e.g., ETA). You could change state here as well governed by your access rights. The button would be hidden if you were below "bug_update_threshold" or you didn't originate it
"Change State to:" - with pull down of allowable / accessible new states based on Victor's state array (or equivalent)
"Assign to:" - with pulldown of developers. The button would be hidden if the assign state were not visible.
"Create Child" - unchanged
"Monitor / End Monitoring" - unchanged
"Move" - unchanged

Does this sound correct?

bblan

bblan

2004-07-21 03:28

reporter   ~0006203

Yes, this is exactly what I thought.

thraxisp

thraxisp

2004-07-24 16:46

reporter   ~0006339

A patch against CVS HEAD + a copy of all the files are attached. I'll commit them after review.

The following files were changed: bug_actiongroup.php bug_report.php bug_report_advanced_page.php bug_report_page.php bug_update_page.php bug_update_advanced_page.php config_defaults_inc.php my_view_page.php view_filters_page.php core/access_api.php core/filter_api.php core/html_api.php core/print_api.php lang/strings_english.txt

The following file was added: bug_change_status_page.php

The new change status page replaced the bug_resolve, bug_reopen and bug_close pages.

thraxisp

thraxisp

2004-07-24 16:51

reporter   ~0006340

Note this patch includes the changes I made in 0003771, and superceeds them.

thraxisp

thraxisp

2004-07-29 20:46

reporter   ~0006466

I updated the files to reflect some feedback.

vboctor

vboctor

2004-07-31 06:50

manager   ~0006493

thraxisp, I emailed you the review for the patch. If you have comments we can discuss on IRC.

thraxisp

thraxisp

2004-08-01 18:24

reporter   ~0006540

Final diffs and modules have been posted. I can commit them tomorrow.

vboctor

vboctor

2004-08-03 08:50

manager   ~0006595

I committed thraxisp changes with some modifications. I attached "change_status.diff" to reflect the changes I have committed compared to CVS. Some of the changes that I can remember:

  • In some places the access level for changing to NEW_ was used instead of report_bug_threshold.
  • In bug_change_status_page.php the bug was not loaded and hence $t_bug was not defined.
  • In the population to "Change Status To" in the view page there was an error in the combobox that $p_val is not defined.
  • I removed status_label_enum, since it will complicate the process of customising statuses. Now the standard status_enum is used.

... and some other minor changes.

thraxisp

thraxisp

2004-08-04 08:09

reporter   ~0006621

fixed in CVS