Skip to content
This repository has been archived by the owner on Feb 8, 2018. It is now read-only.

Relax open work requirement #4221

Merged
merged 5 commits into from
Dec 12, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
language: python
addons:
postgresql: 9.3
branches:
only:
- master
before_install:
- git branch -vv | grep '^*'
- pwd
Expand Down
33 changes: 14 additions & 19 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,23 @@
#Contributing to Gratipay

##What is "open work"?
At http://gratipay.com/about, we have a definition:

> “Open work” means that your company or organization makes it easy for any individual to do your work for you without asking you first, and as a result to share in any revenue you generate.

Do work first, ask permission later. Fun, isn't it? If you are opening a new issue or submitting a pull request, **go for it!** Don't be afraid that it's a dumb idea or a duplicate of another issue or an unwanted change or whatever. Maybe it is! We're still glad to have you! :^)
If you are opening a new issue or submitting a pull request, **go for it!** Don't be afraid that it's a dumb idea or a duplicate of another issue or an unwanted change or whatever. Maybe it is! We're still glad to have you! 💃

##How you can contribute
Whether you are a programmer or not, you can contribute to Gratipay. Below are some ideas we've modified from [this great blog post](http://blog.smartbear.com/programming/14-ways-to-contribute-to-open-source-without-being-a-programming-genius-or-a-rock-star/) (more details at the link). You can check out a similar list [here](http://24pullrequests.com/contributing). If you see anything below that doesn't make sense, _relax_--find something you understand and start from there.
Whether you are a programmer or not, you can contribute to Gratipay. Below are some ideas we've modified from [this great blog post](http://blog.smartbear.com/programming/14-ways-to-contribute-to-open-source-without-being-a-programming-genius-or-a-rock-star/) (more details at the link). You can check out a similar list [here](http://24pullrequests.com/contributing). If you see anything below that doesn't make sense, _relax_—find something you understand and start from there.

1. Follow along on GitHub. Looks like you're in the right place already! See all project repositories at http://github.com/gratipay.
2. Follow the [Gratipay blog](https://medium.com/gratipay-blog).
3. Diagnose a bug by creating an issue.
3. Suggest an improvement by creating an issue.
4. Close resolved issues ([here's the big list](https://github.com/issues?q=is%3Aopen+user%3Agratipay+sort%3Aupdated-desc)).
5. [Test the code](https://github.com/gratipay/gratipay.com/blob/master/README.md).
6. Fix a bug/resolve an issue.
7. Write a test.
8. Add a comment to the code.
11. Create an example.
12. Answer a question.
13. Write a blog post.
14. Improve the website (either [gratipay.com](http://gratipay.com) or [inside.gratipay.com](http://inside.gratipay.com)).
1. Follow the [Gratipay blog](https://medium.com/gratipay-blog).
1. Diagnose a bug by creating an issue.
1. Suggest an improvement by creating an issue.
1. Close resolved issues ([here's the big list](https://github.com/issues?q=is%3Aopen+user%3Agratipay+sort%3Aupdated-desc)).
1. [Test the code](https://github.com/gratipay/gratipay.com/blob/master/README.md).
1. Fix a bug/resolve an issue.
1. Write a test.
1. Add a comment to the code.
1. Create an example.
1. Answer a question.
1. Write a blog post.
1. Improve the website (either [gratipay.com](http://gratipay.com) or [inside.gratipay.com](http://inside.gratipay.com)).

###More info
If you want to really get involved, then check out our [full documentation for contributors](http://inside.gratipay.com/).
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
[![Build Status](http://img.shields.io/travis/gratipay/gratipay.com/master.svg)](https://travis-ci.org/gratipay/gratipay.com)
[![Open Bounties](https://api.bountysource.com/badge/team?team_id=423&style=bounties_received)](https://www.bountysource.com/teams/gratipay/issues)

[Gratipay](http://gratipay.com) provides payments and payouts for open work,
[Gratipay](http://gratipay.com) helps companies fund open source,
in order to cultivate an economy of gratitude, generosity, and love.


Expand Down
11 changes: 4 additions & 7 deletions gratipay/models/team/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,9 @@ def insert(cls, owner, **fields):

INSERT INTO teams
(slug, slug_lower, name, homepage,
product_or_service, todo_url, onboarding_url,
owner)
product_or_service, owner)
VALUES (%(slug)s, %(slug_lower)s, %(name)s, %(homepage)s,
%(product_or_service)s, %(todo_url)s, %(onboarding_url)s,
%(owner)s)
%(product_or_service)s, %(owner)s)
RETURNING teams.*::teams

""", fields)
Expand Down Expand Up @@ -170,7 +168,7 @@ def get_payment_distribution(self):

def update(self, **kw):
updateable = frozenset(['name', 'product_or_service', 'homepage',
'onboarding_url', 'todo_url'])
'onboarding_url'])

cols, vals = zip(*kw.items())
assert set(cols).issubset(updateable)
Expand Down Expand Up @@ -320,8 +318,7 @@ def to_dict(self):
'owner': '~' + self.owner,
'receiving': self.receiving,
'slug': self.slug,
'status': self.status,
'todo_url': self.todo_url
'status': self.status
}


Expand Down
6 changes: 2 additions & 4 deletions gratipay/testing/harness.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,10 +168,10 @@ def make_team(self, *a, **kw):

team = self.db.one("""
INSERT INTO teams
(slug, slug_lower, name, homepage, product_or_service, todo_url,
(slug, slug_lower, name, homepage, product_or_service,
onboarding_url, owner, is_approved, available)
VALUES (%(slug)s, %(slug_lower)s, %(name)s, %(homepage)s, %(product_or_service)s,
%(todo_url)s, %(onboarding_url)s, %(owner)s, %(is_approved)s,
%(onboarding_url)s, %(owner)s, %(is_approved)s,
%(available)s)
RETURNING teams.*::teams
""", _kw)
Expand Down Expand Up @@ -321,5 +321,3 @@ def get_tip(self, tipper, tippee):
LIMIT 1

""", (tipper, tippee), back_as=dict, default=default)['amount']


2 changes: 1 addition & 1 deletion gratipay/utils/fake_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ def fake_team(db, teamowner, teamname=None):
teamname = faker.first_name() + fake_text_id(3)

ctime = teamowner.ctime + datetime.timedelta(days=7)

try:
teamslug = slugize(teamname)
homepage = 'http://www.example.org/' + fake_text_id(3)
Expand All @@ -153,7 +154,6 @@ def fake_team(db, teamowner, teamname=None):
, homepage=homepage
, ctime=ctime
, product_or_service=random.sample(productorservice,1)[0]
, todo_url=homepage + '/tickets'
, onboarding_url=homepage + '/contributing'
, owner=teamowner.username
, is_approved=random.sample(isapproved,1)[0]
Expand Down
5 changes: 5 additions & 0 deletions sql/branch.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
--https://github.com/gratipay/gratipay.com/pull/4214

BEGIN;
ALTER TABLE teams DROP COLUMN todo_url;
END;
4 changes: 1 addition & 3 deletions templates/about-features.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
{% block subnav %}
{% set current_page = request.path.raw.split('/')[3] %}
{% set nav_base = '/about/features' %}
{% set pages = [ ('/', _('Overview'))
, ('/payments', _('Payments'))
, ('/payroll', _('Payroll'))
{% set pages = [ ('/', _('Payments'))
, ('/dnt', _('Do Not Track'))
] %}
{% include "templates/nav.html" %}
Expand Down
7 changes: 2 additions & 5 deletions tests/py/test_pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def test_twitter_associate(self):
assert self.client.GxT('/on/twitter/associate').code == 400

def test_about(self):
expected = "We provide voluntary"
expected = "We help companies pay"
actual = self.client.GET('/about/').body
assert expected in actual

Expand All @@ -134,10 +134,7 @@ def test_about_teams_redirect(self):
assert self.client.GxT('/about/features/teams/').code == 302

def test_about_payments(self):
assert "Payments" in self.client.GET('/about/features/payments').body.decode('utf8')

def test_about_payroll(self):
assert "Payroll" in self.client.GET('/about/features/payroll').body.decode('utf8')
assert "Payments" in self.client.GET('/about/features/').body.decode('utf8')

def test_404(self):
response = self.client.GET('/about/four-oh-four.html', raise_immediately=False)
Expand Down
80 changes: 43 additions & 37 deletions tests/py/test_team_edit.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,22 +241,19 @@ def test_edit(self):
'name': 'Enterprise',
'product_or_service': 'We save galaxies.',
'homepage': 'http://starwars-enterprise.com/',
'onboarding_url': 'http://starwars-enterprise.com/onboarding',
'todo_url': 'http://starwars-enterprise.com/todos',
'image': FileUpload(IMAGE, 'logo.png'),
}
data = json.loads(self.client.POST( '/enterprise/edit/edit.json'
, data=edit_data
, auth_as='picard').body)
, auth_as='picard'
).body)

team = T('enterprise')
assert data == team.to_dict()

assert team.name == 'Enterprise'
assert team.product_or_service == 'We save galaxies.'
assert team.homepage == 'http://starwars-enterprise.com/'
assert team.onboarding_url == 'http://starwars-enterprise.com/onboarding'
assert team.todo_url == 'http://starwars-enterprise.com/todos'
assert team.load_image('original') == IMAGE

def test_edit_supports_partial_updates(self):
Expand All @@ -267,21 +264,21 @@ def test_edit_supports_partial_updates(self):
'image': FileUpload(IMAGE, 'logo.png'),
}
self.client.POST( '/enterprise/edit/edit.json'
, data=edit_data
, auth_as='picard')
, data=edit_data
, auth_as='picard'
)

team = T('enterprise')
assert team.name == 'The Enterprise'
assert team.product_or_service == 'We save galaxies.'
assert team.homepage == 'http://starwars-enterprise.com/'
assert team.onboarding_url == ''
assert team.todo_url == ''
assert team.load_image('original') == IMAGE

def test_edit_needs_auth(self):
self.make_team(slug='enterprise', is_approved=True)
response = self.client.PxST( '/enterprise/edit/edit.json'
, data={ 'name': 'Enterprise' })
, data={'name': 'Enterprise'}
)
assert response.code == 401
assert T('enterprise').name == 'The Enterprise'

Expand All @@ -291,14 +288,16 @@ def test_only_admin_and_owner_can_edit(self):
self.make_team(slug='enterprise', is_approved=True)

response = self.client.PxST( '/enterprise/edit/edit.json'
, data={ 'name': 'Enterprise' }
, auth_as='alice')
, data={'name': 'Enterprise'}
, auth_as='alice'
)
assert response.code == 403
assert T('enterprise').name == 'The Enterprise'

response = self.client.POST( '/enterprise/edit/edit.json'
, data={ 'name': 'Enterprise' }
, auth_as='admin')
, data={'name': 'Enterprise'}
, auth_as='admin'
)
assert response.code == 200
assert T('enterprise').name == 'Enterprise'

Expand All @@ -309,39 +308,43 @@ def test_cant_edit_closed_teams(self):
self.db.run("UPDATE teams SET is_closed = true WHERE slug = 'enterprise'")

response = self.client.PxST( '/enterprise/edit/edit.json'
, data={ 'name': 'Enterprise' }
, auth_as='picard')
, data={'name': 'Enterprise'}
, auth_as='picard'
)
assert response.code in (403, 410)
assert T('enterprise').name == 'The Enterprise'

def test_cant_edit_rejected_teams(self):
self.make_team(slug='enterprise', is_approved=False)
response = self.client.PxST( '/enterprise/edit/edit.json'
, data={ 'name': 'Enterprise' }
, auth_as='picard')
, data={'name': 'Enterprise'}
, auth_as='picard'
)
assert response.code == 403
assert T('enterprise').name == 'The Enterprise'

def test_can_edit_teams_under_review(self):
self.make_team(slug='enterprise', is_approved=None)
response = self.client.POST( '/enterprise/edit/edit.json'
, data={ 'name': 'Enterprise' }
, auth_as='picard')
, data={'name': 'Enterprise'}
, auth_as='picard'
)
assert response.code == 200
assert T('enterprise').name == 'Enterprise'

def test_can_only_edit_allowed_fields(self):
allowed_fields = set(['name', 'image', 'product_or_service',
'homepage', 'onboarding_url', 'todo_url'])
allowed_fields = set(['name', 'image', 'product_or_service', 'homepage'])

team = self.make_team(slug='enterprise', is_approved=None)

fields = vars(team).keys()
fields.remove('onboarding_url') # we are still keeping this in the db for now
for field in fields:
if field not in allowed_fields:
response = self.client.POST( '/enterprise/edit/edit.json'
, data={ field: 'foo' }
, auth_as='picard')
, data={field: 'foo'}
, auth_as='picard'
)
new_team = T('enterprise')
assert response.code == 200
assert getattr(new_team, field) == getattr(team, field)
Expand All @@ -351,30 +354,33 @@ def test_edit_accepts_jpeg_and_png(self):
image_types = ['png', 'jpg', 'jpeg']
for i_type in image_types:
team.save_image(original='', large='', small='', image_type='image/png')
data = { 'image': FileUpload(IMAGE, 'logo.'+i_type) }
data = {'image': FileUpload(IMAGE, 'logo.'+i_type)}
response = self.client.POST( '/enterprise/edit/edit.json'
, data=data
, auth_as='picard')
, data=data
, auth_as='picard'
)
assert response.code == 200
assert team.load_image('original') == IMAGE

def test_edit_with_invalid_image_type_raises_error(self):
team = self.make_team(slug='enterprise', is_approved=True)
invalid_image_types = ['tiff', 'gif', 'bmp', 'svg']
for i_type in invalid_image_types:
data = { 'image': FileUpload(IMAGE, 'logo.'+i_type) }
data = {'image': FileUpload(IMAGE, 'logo.'+i_type)}
response = self.client.PxST( '/enterprise/edit/edit.json'
, data=data
, auth_as='picard')
, data=data
, auth_as='picard'
)
assert response.code == 400
assert "Please upload a PNG or JPG image." in response.body
assert team.load_image('original') == None

def test_edit_with_empty_values_raises_error(self):
self.make_team(slug='enterprise', is_approved=True)
response = self.client.PxST( '/enterprise/edit/edit.json'
, data={ 'name': ' ' }
, auth_as='picard')
, data={'name': ' '}
, auth_as='picard'
)
assert response.code == 400
assert T('enterprise').name == 'The Enterprise'

Expand All @@ -384,8 +390,9 @@ def test_edit_with_bad_url_raises_error(self):
, homepage='http://starwars-enterprise.com/')

r = self.client.PxST( '/enterprise/edit/edit.json'
, data={ 'homepage': 'foo' }
, auth_as='picard')
, data={'homepage': 'foo'}
, auth_as='picard'
)
assert r.code == 400
assert "Please enter an http[s]:// URL for the 'Homepage' field." in r.body
assert T('enterprise').homepage == 'http://starwars-enterprise.com/'
Expand All @@ -397,13 +404,12 @@ def test_edit_with_empty_data_does_nothing(self):
'name': 'Enterprise',
'product_or_service': 'We save galaxies.',
'homepage': 'http://starwars-enterprise.com/',
'onboarding_url': 'http://starwars-enterprise.com/onboarding',
'todo_url': 'http://starwars-enterprise.com/todos',
}
self.make_team(**team_data)
r = self.client.POST( '/enterprise/edit/edit.json'
, data={}
, auth_as='picard')
, auth_as='picard'
)
assert r.code == 200

team = T('enterprise')
Expand Down
Loading