Trac Workflow blocking - workflow

Is there a way to block a given change based on the user role?
For example, I don't want any developer to be able to change a ticket status from 'development' to 'closed'. I want it to go through 'test', and allow 'test' to 'closed' only to users with the test role.

This is pretty straightforward tweak to the Trac Workflow. The documentation for adding optional testing is quoted below:
By adding the following to your
[ticket-workflow] section of trac.ini
you get optional testing. When the
ticket is in new, accepted or
needs_work status you can choose to
submit it for testing. When it's in
the testing status the user gets the
option to reject it and send it back
to needs_work, or pass the testing and
send it along to closed. If they
accept it then it gets automatically
marked as closed and the resolution is
set to fixed. Since all the old work
flow remains, a ticket can skip this
entire section.
testing = new,accepted,needs_work,assigned,reopened -> testing
testing.name = Submit to reporter for testing
testing.permissions = TICKET_MODIFY
reject = testing -> needs_work
reject.name = Failed testing, return to developer
pass = testing -> closed
pass.name = Passes Testing
pass.operations = set_resolution
pass.set_resolution = fixed
Now all tickets must go through the "testing" state before the "pass" state.
To ensure that only certain testers can change a ticket from "testing" to "pass", create a new permission called TICKET_PASS (the trac admin can do this in the web UI), and add the following to your the workflow section of your trac.ini:
pass.permissions = TICKET_PASS
IMHO, it's sufficient to just require that tickets go through testing before they pass. Any reasonable developer knows that they shouldn't move a ticket from the "testing" state to the "passing" state unless it's passed whatever quality control you do. And since there's a history of their actions, they can be blamed for inappropriately marking tickets as "pass". Restricting the privileges will probably get in the way (distracting the trac admin) more than it helps.
[NB: I had to remove all but one of the hyperlinks to documentation b/c my rep is too low. Sigh.]

Related

Support multi-site approval based workflow on wagtail

Objective
We would like to setup multi-site wagtail with approval chain.
Develop -> QA -> Release -> Production
Description
A develop / content editor goes to the wagtail admin and creates the content. Once done, sends the request for approval to move to QA site.
QA moderator reviews the content on develop site. If approved, the content gets moved to QA site. The content carries over to next stage approval (release).
Same process ahead for next sites in approval chain.
Questions
Is it possible to setup a publish chain with approval policy in wagtail? I tried to research a bit but could only find "workflow" and "workflow tasks". Do I need to custom code a workflow task to be able to achieve this?
This should be possible but you will need to consider what you really want to do in regards to the 'move' step, do you want to actually move the Page instance to a new site in a new tree or copy the current (and its history) and move that copy Page OR make a copy to put in place of the Page that was moved.
Nonetheless, the documentation on how to add a new Task type is the best place to start, it walks you through custom Task types.
In the solution below however, I thought it would be simplest to create a new model that behaves exactly like GroupApprovalTask (the default task included, used for moderation) but add a field that links it to the Site model.
This way, in the admin UI the admin users can now create as many PublishSiteTask as you want, one for each Site (QA/Dev/Prod etc) and then each of those could be linked to different user groups. It is important to differentiate between the database model (a task type with some fields) and the instances (a task created in the UI) and the actual task instances that are created against each page revision (not page) as the workflow steps progress.
Code Example
models.py
from django.db import models, transaction
from wagtail.core.models import GroupApprovalTask, Page, Site
# ... other imports
class PublishSiteTask(GroupApprovalTask):
site = models.OneToOneField(Site, on_delete=models.CASCADE)
admin_form_fields = ['site'] + GroupApprovalTask.admin_form_fields
#transaction.atomic
def on_action(self, task_state, user, action_name, **kwargs):
"""Performs an action on a task state determined by the ``action_name`` string passed"""
if action_name == 'approve':
# get the page that this action is referring to via the task_state.page_revision
page = task_state.page_revision.as_page_object()
# find the new parent target at this task's site
# how this is done depends on the site/page structure
new_parent_target = self.site.root_page
# move the page to a new location
# note: this will actually move it from its current tree, you may want to make a copy first
page.move(new_parent_target)
# be sure to preserve any existing task behaviour
super().on_action(task_state, user, action_name, **kwargs)
Additional Links
Task class definition
GroupApprovalTask class definition
You may want to do some pre-work in the code to check that the page can actually move to the different Site, each Page has a method can_move_to that could help.
The move method referenced above is part of the Wagtail code but the full docs for that method can be found in the Treebeard API docs which Wagtail uses to manage the tree structure.

modify existing promotion, what happens to the user profiles who already have it?

I have created a promotion promoxyz with unilimited access and create coupon couponxyz which uses promoxyz, and gave it to user1 , he used it so promoxyz is saved in his active promotions as unlimited.
No after some time the business wanted the promoxyz to be limited to max use of "1", so the max number of uses is changed to "1" and published through BCC.
Now my question is why is the user1 is able to continue to use it as unlimited, Aparantly the updated promotion has no effect on user1. Is there a way to force the user1 promotions to point the latest setting in this case only once usage ?
Thanks
It is not effected becoz the latest change in the promotion asset is done in the BCC ie., in publishing server .But where as when user1 is using the promotion it is taking this promotion copy from production server.So unless you have the latest copy in production.You cant see the effected change.But still you can go in short cut.There are two ways
Deploy the version of your promotion in production server again.This
is traditional way.
Else go to dyn admin of production and then to
claimable repository/Product catalog (where ever your promotion
repository item is) and use
<update-item item-descriptor="your promo item descriptor" id="your promo id">
<set-property name="global"><![CDATA[false]]></set-property> <!-- Automatically apply to all orders -->
<set-property name="giveToAnonymousProfiles"><![CDATA[false]]></set-property> <!-- Give to anonymous customers -->
</update-item>
and in your API code do grant the promotion explicitly to that user to whom you want to.
PromotionTools.grantPromotion("userId(not login id)", "promotionId");
The recommended approach is to not modify existing promotions.
You should expire the current promotion (by adding an end date), and create a new one with an appropriate start date.

GWT RequestFactory: check if members have been set without permission

I am working with GWT / RequestFactory and a set of customer requirements regarding permissions. Let me explain a basic example:
Every user is assigned to a company. Every user should be able to edit company's core data - but only e.g contact information, website etc. Security-relevant ones like BIC/SWIFT, IBAN, Company name and so on can only be changed if the user has a certain permission XY.
So far so good, on the client side I can check the permissions and disable those fields the user is not allowed to edit. But what would be the most elegant way to ensure on the server side that those fields have not been set without permission?
My problem is that I cannot track changes on the server side. Having #PreAuthorize on every setter is not an option too, because it would end in an authorization-massacre in each and every entity.
At the moment I am following a workaround: every field that is secured / depends on a given permission is passed as an argument to the entity-method and is excluded from the proxy. That way, values cannot be set using the proxy and I can check in my server code if the user has permissions. If not, nothing happens. If user has permissions, I set the values manually. But that produces a lot of boilerplate-code and ugly method signatures because the number of values passed to the method could get large.
I hope you understand my issue. I'm looking forward for your opinions and tips. Thank you in advance.
Well, you can receive many answers (different each other), and all of them could be right, so, at the end is your call. Wait for others answers. I am going to give you the approach that I followed (and it worked pretty well). :D.
Under my opinion, the server should do less as possible, so keep the logic for allowing modify each param on the server I think it is not a scalable solution (if your system has 1M users modifying everything at the same time, will your server work fluent?). I prefer let the client do the job (like Roomba :D).
For solving that problem, in our system we implemented an Access Control List solution. You can store in your db, on each user entity, a list with granted permissions. So, when that information arrives to the client (after user's log in, for example), you can get them, and show the fields that he/she is allow to modify.
Something like:
if (canModifyPersonalDetails(user.getAcls(), ...) ) {
//show labels ...
}
if (canModifyBankDetails(user.getAcls(), ...) ) {
//show labels
}
You can not avoid server call for log in, so it is not a big deal send the extra information (think about the ACLs could be simple list of integers 0 means personal details, 1 bank details....).
If you are dealing with very compromised information and you prefer do some stuff on the server, in that case probably I'd set up a security level, when you are persisting/updating your proxy, I'd do something like:
if (isAllowForPersonalDetails(user.getSecurityCode()) {
//update the modified personal details
}
if (isAllowForBankDetails(user.getSecurityCode()) {
//update the modified bank details
}
user.update();
I am a big fan of clear User GUI's, and a very big fan of let the server free as much as possible, so I prefer the first option. But if you have constraints for modifying user entity in db, or you prefer do not modify your views, or any constraint with security, maybe the second option is the best one for you.
Hope that helps!

Multiple scenarios within a specification feature file?

After having gotten more comfortable in Behaviour-Driven Developement using SpecFlow, I was wondering about having multiple scenarios for the same feature as follows:
Register.feature
Feature: Register a new user
In order to use the system,
one must register with the system
so that one gets authorized and may login
Scenario: Register a new user using valid credentials
Given I am on the registration page
When I have entered my desired username "UserName" and password "password"
And I have confirmed my password "password"
And I click the register button
Then I shall get confirmation that I am now a registered user
Beside the fact that my scenario might have gotten a bit too fat, one must also manage to validate other scenarios within the registration process such as:
Input user name is too short
Input password is too short
Input password doesn't contain numbers
Input password doesn't match the confirm password
Just to name a few. I have read about tags using SpecFlow Feature File so that I could perhaps do as follows:
#shorterPasswordProvided
Scenario: Register a user using a password that is too short
Given I am on the registration page
When I have entered my desired user name
And I have provided a password that is too short "allo"
And I click the Register button
Then I shall get an error message which mentions about the password minimum length
#noCredentialsAtAll
Scenario: Register a user using no credentials at all
Given I am on the registration page
When I click on the Register button with no credentials entered
Then I shall get an error message that says I have to fill all required fields in
Then, using the [BeforeScenario("myTag")] should do the trick.
The hooks allows for the execution of a subset of the tests to be executed following certain rules. So, a When method could then be executed with a predefined context, that is, the hook for which it was meant to be executed, and that is mentioned through the BeforeScenario or the like attribute.
Have I understood correctly, or am I in fog here?
Am I pushing too far?
Am I missing something?
Are all the "too short password", "no credentials provided" considered different usage scenarios, or are they something else which could only fit somewhere else in the code, like the unit tests themselves?
I mean, all those scenarios belongs to the Register feature, and as such, they shall be defined in the same Register.feature SpecFlow Feature File, right?
Ok, you have a couple of questions, so I'll work through them:
Then, using the [BeforeScenario("myTag")] should do the trick.
The BeforeScenario hook attribute is used to run some code before the scenario executes. It's often used to set-up the environment for the scenario (e.g. populate the test database with pertinent data); if used for this purpose, then the use of AfterScenario can also be used to clean-up the result of BeforeScenario.
The hooks allows for the execution of a subset of the tests to be
executed following certain rules. So, a When method could then be
executed with a predefined context
If I understand you correctly, you want to be able to use a tag to control when a step within the scenario can be run/not-run. This is not possible with SpecFlow's hook attributes; there is a BeforeStep hook but this only enables you to execute code before the step is run, it doesn't allow the step to be ignored.
Are all the "too short password", "no credentials provided" considered
different usage scenarios, or are they something else which could only
fit somewhere else in the code, like the unit tests themselves?
In your example, yes these are different scenarios for your "Register a new user" feature. If you are taking a strict BDD approach to your development, then with your "outside-in inside-out" development approach you will also implement unit tests (by falling back to TDD as part of the BDD process) which will also cover the "too short password" and "no credentials provided" validation.
As for your scenario:
When I have entered my desired username "UserName" and password "password"
Instead of using this, use:
When I enter my username "UserName"
And I enter my password "password"
By doing this you will be able to re-use "When I enter my password" in "Register a user using a password that is too short". This leads me onto:
And I have provided a password that is too short "allo"
There is no need to have a separate step which states the password is too short. Just re-use:
When I enter my password "allo"
For the same reason, don't use:
When I click on the Register button with no credentials entered
just reuse:
When I click on the Register button

Implementing "Report this content" and detecting spammer or robot triggered event

I'm creating a forum for a website, and plan on implementing a "Report this content" function.
In all honesty, I'm not sure how useful (lit. necessary) the feature will be, since a user account (created by admin) will be required for posting, but the solution interests me.
So in short, this is the scenario:
For all users, there will be read-only access to all (non-restricted) content on the forum. For unidentified users there will be a reply button and report this content button present. The former will proceed to require a login, while I had planned that the latter wouldn't, so that anyone would be able to flag suspicious or offensive content.
The problem I'm thus facing is basically "robot clicks", or rather how to implement the system so it won't be fooled by "robot clicks".
There are a few methods that come to mind:
1) User-agent
2) Requiring several flags (in a predefined timespan?) before reacting in any way
3) robots.txt
4) Requiring human input on a second form (captcha or "specify reason")
What I think of them:
1) Unreliable (as sole solution)
2) This requires a mass of users which might lead to the event never being triggered
3) This is probably the "right" way to go, but will only work for those who respect it
4) Meh, I hate captcha and requiring a reason might raise the bar too high to keep the function useful
What methods would the (highly enlightened) community have to share with me?
You could append the 'report this' <form> to the DOM with javascript's appendChild();.
This would prevent a lot of spam.
It would also prevent users not running javascript from seeing the report button. But since this is a feature that does not hinder the user-experience, it is probably an acceptable option.
window.onload = function() {
var f = document.createElement('FORM');
f.method = 'post';
f.action = 'report.cgi';
var b = document.createElement('INPUT');
b.type = 'submit';
b.value = 'Report this';
f.appendChild(b);
document.body.appendChild(f);
}
Note:
The rel="nofollow" attribute makes sure search engines do not 'count' the link, they do however follow it (yes, the name suggests differently).
If you want the search engines not to touch a certain file, use robots.txt
Note 2:
Reporting something is an action that 'changes' something on the server. Thus, it should not be a GET request Instead it should be a POST request. In other words: do not use a <a href""> but instead submit a <form> with its method argument set to "post".
You could simply redirect to a form where the user needs to enter a reason for reporting the content. A robot probably would not enter anything here and the form would not be processed if the user didn't enter anything.
You missed making the link a nofollow one, but I'd opt for a combination of requiring human input (reason, details of complainant) to counter robots and requiring a number of flags to stop people just flagging people they disagree with/don't like on the forum.