@@ -33,6 +33,11 @@ contract Tasks is DSMath {
3333 /// @param taskId The newly added task id
3434 event TaskAdded (uint256 taskId );
3535
36+ /// @notice Event logged when a task's security status changes (secure vs. managed)
37+ /// @param taskId Id of the task
38+ /// @param secure Boolean of security status (true: secure, false: managed)
39+ event TaskSecuritySet (uint256 indexed taskId , bool secure );
40+
3641 /// @notice Event logged when a task's specification hash changes
3742 /// @param taskId Id of the task
3843 /// @param specificationHash New specification hash of the task
@@ -69,6 +74,7 @@ contract Tasks is DSMath {
6974 uint256 dueDate;
7075 uint256 completionTimestamp;
7176 uint256 changeNonce;
77+ bool secure;
7278 }
7379
7480 struct Role {
@@ -103,6 +109,7 @@ contract Tasks is DSMath {
103109 roleAssignmentSigs[bytes4 (keccak256 ("setTaskWorkerRole(uint256,address) " ))] = true ;
104110
105111 // Initialise the task update reviewers
112+ reviewers[bytes4 (keccak256 ("setTaskSecurity(uint256,bool) " ))] = [TaskRole.Manager, TaskRole.Worker];
106113 reviewers[bytes4 (keccak256 ("setTaskBrief(uint256,bytes32) " ))] = [TaskRole.Manager, TaskRole.Worker];
107114 reviewers[bytes4 (keccak256 ("setTaskDueDate(uint256,uint256) " ))] = [TaskRole.Manager, TaskRole.Worker];
108115 reviewers[bytes4 (keccak256 ("setTaskSkill(uint256,uint256) " ))] = [TaskRole.Manager, TaskRole.Worker];
@@ -115,8 +122,8 @@ contract Tasks is DSMath {
115122 reviewers[bytes4 (keccak256 ("cancelTask(uint256) " ))] = [TaskRole.Manager, TaskRole.Worker];
116123 }
117124
118- modifier self () {
119- require (address (this ) == msg .sender , "task-not-self " );
125+ modifier self (uint256 _id ) {
126+ require (managerCanCall (_id) || address (this ) == msg .sender , "task-not-self " );
120127 _;
121128 }
122129
@@ -131,6 +138,16 @@ contract Tasks is DSMath {
131138 _;
132139 }
133140
141+ modifier taskSecure (uint256 _id ) {
142+ require (isTaskSecure (_id), "task-not-secure " );
143+ _;
144+ }
145+
146+ modifier taskManaged (uint256 _id ) {
147+ require (! isTaskSecure (_id), "task-not-managed " );
148+ _;
149+ }
150+
134151 modifier taskComplete (uint256 _id ) {
135152 require (isTaskComplete (_id), "task-not-complete " );
136153 _;
@@ -162,12 +179,10 @@ contract Tasks is DSMath {
162179 bytes4 sig;
163180 uint256 taskId;
164181 (sig, taskId) = deconstructCall (_data);
165- require (taskId > 0 && taskId <= taskCount, "task-does-not-exist " );
182+ require (doesTaskExist (taskId), "task-does-not-exist " );
183+ require (! isTaskComplete (taskId), "task-complete " );
166184 require (! roleAssignmentSigs[sig], "task-change-is-role-assign " );
167185
168- ColonyDataTypes.ExpenditureStatus status = colony.getExpenditure (tasks[taskId].expenditureId).status;
169- require (status != ColonyDataTypes.ExpenditureStatus.Finalized, "task-finalized " );
170-
171186 uint8 nSignaturesRequired;
172187 address taskRole1User = getTaskRoleUser (taskId, TaskRole (reviewers[sig][0 ]));
173188 address taskRole2User = getTaskRoleUser (taskId, TaskRole (reviewers[sig][1 ]));
@@ -219,12 +234,10 @@ contract Tasks is DSMath {
219234 uint256 taskId;
220235 address userAddress;
221236 (sig, taskId, userAddress) = deconstructRoleChangeCall (_data);
222- require (taskId > 0 && taskId <= taskCount, "task-does-not-exist " );
237+ require (doesTaskExist (taskId), "task-does-not-exist " );
238+ require (! isTaskComplete (taskId), "task-complete " );
223239 require (roleAssignmentSigs[sig], "task-change-is-not-role-assign " );
224240
225- ColonyDataTypes.ExpenditureStatus status = colony.getExpenditure (tasks[taskId].expenditureId).status;
226- require (status != ColonyDataTypes.ExpenditureStatus.Finalized, "task-finalized " );
227-
228241 uint8 nSignaturesRequired;
229242 address manager = getTaskRoleUser (taskId, TaskRole.Manager);
230243 // If manager wants to set himself to a role
@@ -274,7 +287,8 @@ contract Tasks is DSMath {
274287 bytes32 _specificationHash ,
275288 uint256 _domainId ,
276289 uint256 _skillId ,
277- uint256 _dueDate
290+ uint256 _dueDate ,
291+ bool _secure
278292 )
279293 public
280294 isAdmin (msg .sender , _callerPermissionDomainId, _callerChildSkillIndex, _domainId)
@@ -285,9 +299,13 @@ contract Tasks is DSMath {
285299 tasks[taskCount].expenditureId = expenditureId;
286300 tasks[taskCount].specificationHash = _specificationHash;
287301 tasks[taskCount].dueDate = (_dueDate > 0 ) ? _dueDate : now + 90 days ; // Note: can set dueDate in past?
302+ tasks[taskCount].secure = _secure;
288303
289304 setTaskRoleUser (taskCount, TaskRole.Manager, msg .sender );
290- setTaskRoleUser (taskCount, TaskRole.Evaluator, msg .sender );
305+
306+ if (_secure) {
307+ setTaskRoleUser (taskCount, TaskRole.Evaluator, msg .sender );
308+ }
291309
292310 if (_skillId > 0 ) {
293311 this .setTaskSkill (taskCount, _skillId);
@@ -299,6 +317,8 @@ contract Tasks is DSMath {
299317
300318 function submitTaskWorkRating (uint256 _id , TaskRole _role , bytes32 _secret )
301319 public
320+ taskExists (_id)
321+ taskSecure (_id)
302322 taskComplete (_id)
303323 {
304324 if (_role == TaskRole.Manager) { // Manager rated by worker
@@ -355,46 +375,56 @@ contract Tasks is DSMath {
355375 return ratingSecrets[_id].secret[_role];
356376 }
357377
378+ function setTaskSecurity (uint256 _id , bool _secure ) public self (_id) {
379+ tasks[_id].secure = _secure;
380+
381+ if (! _secure) {
382+ removeTaskEvaluatorRole (_id);
383+ }
384+
385+ emit TaskSecuritySet (_id, _secure);
386+ }
387+
358388 // Note: the domain permissions arguments are placed at the end for consistency with the other role change functions
359389 function setTaskManagerRole (uint256 _id , address payable _user , uint256 _permissionDomainId , uint256 _childSkillIndex )
360390 public
361- self
391+ self (_id)
362392 isAdmin (_user, _permissionDomainId, _childSkillIndex, colony.getExpenditure (tasks[_id].expenditureId).domainId)
363393 {
364394 setTaskRoleUser (_id, TaskRole.Manager, _user);
365395 }
366396
367- function setTaskEvaluatorRole (uint256 _id , address payable _user ) public self {
397+ function setTaskEvaluatorRole (uint256 _id , address payable _user ) public self (_id) taskSecure (_id) {
368398 // Can only assign role if no one is currently assigned to it
369399 require (getTaskRoleUser (_id, TaskRole.Evaluator) == address (0x0 ), "task-evaluator-role-assigned " );
370400 setTaskRoleUser (_id, TaskRole.Evaluator, _user);
371401 }
372402
373- function setTaskWorkerRole (uint256 _id , address payable _user ) public self {
403+ function setTaskWorkerRole (uint256 _id , address payable _user ) public self (_id) {
374404 // Can only assign role if no one is currently assigned to it
375405 require (getTaskRoleUser (_id, TaskRole.Worker) == address (0x0 ), "task-worker-role-assigned " );
376406 uint256 [] memory skills = colony.getExpenditureSlot (tasks[_id].expenditureId, uint256 (TaskRole.Worker)).skills;
377407 require (skills.length > 0 && skills[0 ] > 0 , "task-skill-not-set " ); // ignore-swc-110
378408 setTaskRoleUser (_id, TaskRole.Worker, _user);
379409 }
380410
381- function removeTaskEvaluatorRole (uint256 _id ) public self {
411+ function removeTaskEvaluatorRole (uint256 _id ) public self (_id) {
382412 setTaskRoleUser (_id, TaskRole.Evaluator, address (0x0 ));
383413 }
384414
385- function removeTaskWorkerRole (uint256 _id ) public self {
415+ function removeTaskWorkerRole (uint256 _id ) public self (_id) {
386416 setTaskRoleUser (_id, TaskRole.Worker, address (0x0 ));
387417 }
388418
389- function setTaskManagerPayout (uint256 _id , address _token , uint256 _amount ) public self {
419+ function setTaskManagerPayout (uint256 _id , address _token , uint256 _amount ) public self (_id) {
390420 colony.setExpenditurePayout (_id, uint256 (TaskRole.Manager), _token, _amount);
391421 }
392422
393- function setTaskEvaluatorPayout (uint256 _id , address _token , uint256 _amount ) public self {
423+ function setTaskEvaluatorPayout (uint256 _id , address _token , uint256 _amount ) public self (_id) {
394424 colony.setExpenditurePayout (_id, uint256 (TaskRole.Evaluator), _token, _amount);
395425 }
396426
397- function setTaskWorkerPayout (uint256 _id , address _token , uint256 _amount ) public self {
427+ function setTaskWorkerPayout (uint256 _id , address _token , uint256 _amount ) public self (_id) {
398428 colony.setExpenditurePayout (_id, uint256 (TaskRole.Worker), _token, _amount);
399429 }
400430
@@ -421,15 +451,14 @@ contract Tasks is DSMath {
421451 this .setTaskWorkerPayout (_id, _token, _workerAmount);
422452 }
423453
424- function setTaskSkill (uint256 _id , uint256 _skillId ) public self {
454+ function setTaskSkill (uint256 _id , uint256 _skillId ) public self (_id) {
425455 colony.setExpenditureSkill (tasks[_id].expenditureId, uint256 (TaskRole.Worker), _skillId);
426456 }
427457
428458 function setTaskBrief (uint256 _id , bytes32 _specificationHash )
429459 public
430- self
460+ self (_id)
431461 taskExists (_id)
432- taskNotComplete (_id)
433462 {
434463 tasks[_id].specificationHash = _specificationHash;
435464
@@ -438,9 +467,8 @@ contract Tasks is DSMath {
438467
439468 function setTaskDueDate (uint256 _id , uint256 _dueDate )
440469 public
441- self
470+ self (_id)
442471 taskExists (_id)
443- taskNotComplete (_id)
444472 {
445473 tasks[_id].dueDate = _dueDate;
446474
@@ -450,6 +478,7 @@ contract Tasks is DSMath {
450478 function submitTaskDeliverable (uint256 _id , bytes32 _deliverableHash )
451479 public
452480 taskExists (_id)
481+ taskSecure (_id)
453482 taskNotComplete (_id)
454483 confirmTaskRoleIdentity (_id, msg .sender , TaskRole.Worker)
455484 {
@@ -468,6 +497,7 @@ contract Tasks is DSMath {
468497 function completeTask (uint256 _id )
469498 public
470499 taskExists (_id)
500+ taskSecure (_id)
471501 taskNotComplete (_id)
472502 confirmTaskRoleIdentity (_id, msg .sender , TaskRole.Manager)
473503 {
@@ -479,17 +509,17 @@ contract Tasks is DSMath {
479509
480510 function cancelTask (uint256 _id )
481511 public
482- self
512+ self (_id)
483513 taskExists (_id)
484- taskNotComplete (_id)
485514 {
486515 colony.cancelExpenditure (tasks[_id].expenditureId);
487516 }
488517
489518 // Permissions pertain to the Arbitration role here
490- function finalizeTask (uint256 _permissionDomainId , uint256 _childSkillIndex , uint256 _id )
519+ function finalizeSecureTask (uint256 _permissionDomainId , uint256 _childSkillIndex , uint256 _id )
491520 public
492521 taskExists (_id)
522+ taskSecure (_id)
493523 taskComplete (_id)
494524 {
495525 colony.finalizeExpenditure (tasks[_id].expenditureId);
@@ -510,6 +540,15 @@ contract Tasks is DSMath {
510540 }
511541 }
512542
543+ function finalizeManagedTask (uint256 _id )
544+ public
545+ taskExists (_id)
546+ taskManaged (_id)
547+ confirmTaskRoleIdentity (_id, msg .sender , TaskRole.Manager)
548+ {
549+ colony.finalizeExpenditure (tasks[_id].expenditureId);
550+ }
551+
513552 function getTaskCount () public view returns (uint256 ) {
514553 return taskCount;
515554 }
@@ -629,12 +668,14 @@ contract Tasks is DSMath {
629668 function taskWorkRatingsAssigned (uint256 _id ) internal view returns (bool ) {
630669 Role storage workerRole = taskRoles[_id][uint8 (TaskRole.Worker)];
631670 Role storage managerRole = taskRoles[_id][uint8 (TaskRole.Manager)];
671+
632672 return (workerRole.rating != TaskRatings.None) && (managerRole.rating != TaskRatings.None);
633673 }
634674
635675 function taskWorkRatingsClosed (uint256 _id ) internal view returns (bool ) {
636676 assert (tasks[_id].completionTimestamp > 0 );
637677 assert (ratingSecrets[_id].count <= 2 );
678+
638679 if (ratingSecrets[_id].count == 2 ) {
639680 return sub (now , ratingSecrets[_id].timestamp) > RATING_REVEAL_TIMEOUT;
640681 } else {
@@ -667,15 +708,8 @@ contract Tasks is DSMath {
667708 }
668709 }
669710
670- function setTaskRoleUser (uint256 _id , TaskRole _role , address payable _user )
671- internal
672- taskExists (_id)
673- taskNotComplete (_id)
674- {
675- taskRoles[_id][uint8 (_role)] = Role ({
676- rateFail: false ,
677- rating: TaskRatings.None
678- });
711+ function setTaskRoleUser (uint256 _id , TaskRole _role , address payable _user ) internal {
712+ taskRoles[_id][uint8 (_role)] = Role ({ rateFail: false , rating: TaskRatings.None });
679713
680714 colony.setExpenditureRecipient (tasks[_id].expenditureId, uint256 (_role), _user);
681715 }
@@ -684,7 +718,15 @@ contract Tasks is DSMath {
684718 return _id > 0 && _id <= taskCount;
685719 }
686720
721+ function isTaskSecure (uint256 _id ) internal view returns (bool ) {
722+ return tasks[_id].secure;
723+ }
724+
687725 function isTaskComplete (uint256 _id ) internal view returns (bool ) {
688726 return tasks[_id].completionTimestamp > 0 ;
689727 }
728+
729+ function managerCanCall (uint256 _id ) internal view returns (bool ) {
730+ return ! tasks[_id].secure && getTaskRoleUser (_id, TaskRole.Manager) == msg .sender ;
731+ }
690732}
0 commit comments