Show More
@@ -0,0 +1,69 b'' | |||
|
1 | # Copyright (C) 2016-2016 RhodeCode GmbH | |
|
2 | # | |
|
3 | # This program is free software: you can redistribute it and/or modify | |
|
4 | # it under the terms of the GNU Affero General Public License, version 3 | |
|
5 | # (only), as published by the Free Software Foundation. | |
|
6 | # | |
|
7 | # This program is distributed in the hope that it will be useful, | |
|
8 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
|
9 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
|
10 | # GNU General Public License for more details. | |
|
11 | # | |
|
12 | # You should have received a copy of the GNU Affero General Public License | |
|
13 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
|
14 | # | |
|
15 | # This program is dual-licensed. If you wish to learn more about the | |
|
16 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
|
17 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
|
18 | ||
|
19 | from datetime import datetime | |
|
20 | from marshmallow import Schema, fields | |
|
21 | from pyramid.threadlocal import get_current_request | |
|
22 | from rhodecode.lib.utils2 import AttributeDict | |
|
23 | ||
|
24 | ||
|
25 | SYSTEM_USER = AttributeDict(dict( | |
|
26 | username='__SYSTEM__' | |
|
27 | )) | |
|
28 | ||
|
29 | ||
|
30 | class UserSchema(Schema): | |
|
31 | """ | |
|
32 | Marshmallow schema for a user | |
|
33 | """ | |
|
34 | username = fields.Str() | |
|
35 | ||
|
36 | ||
|
37 | class RhodecodeEventSchema(Schema): | |
|
38 | """ | |
|
39 | Marshmallow schema for a rhodecode event | |
|
40 | """ | |
|
41 | utc_timestamp = fields.DateTime() | |
|
42 | acting_user = fields.Nested(UserSchema) | |
|
43 | acting_ip = fields.Str() | |
|
44 | ||
|
45 | ||
|
46 | class RhodecodeEvent(object): | |
|
47 | """ | |
|
48 | Base event class for all Rhodecode events | |
|
49 | """ | |
|
50 | MarshmallowSchema = RhodecodeEventSchema | |
|
51 | ||
|
52 | def __init__(self): | |
|
53 | self.request = get_current_request() | |
|
54 | self.utc_timestamp = datetime.utcnow() | |
|
55 | ||
|
56 | @property | |
|
57 | def acting_user(self): | |
|
58 | if self.request: | |
|
59 | return self.request.user.get_instance() | |
|
60 | return SYSTEM_USER | |
|
61 | ||
|
62 | @property | |
|
63 | def acting_ip(self): | |
|
64 | if self.request: | |
|
65 | return self.request.user.ip_addr | |
|
66 | return '<no ip available>' | |
|
67 | ||
|
68 | def as_dict(self): | |
|
69 | return self.MarshmallowSchema().dump(self).data No newline at end of file |
@@ -831,6 +831,19 b'' | |||
|
831 | 831 | license = [ pkgs.lib.licenses.bsdOriginal ]; |
|
832 | 832 | }; |
|
833 | 833 | }; |
|
834 | marshmallow = super.buildPythonPackage { | |
|
835 | name = "marshmallow-2.8.0"; | |
|
836 | buildInputs = with self; []; | |
|
837 | doCheck = false; | |
|
838 | propagatedBuildInputs = with self; []; | |
|
839 | src = fetchurl { | |
|
840 | url = "https://pypi.python.org/packages/4f/64/9393d77847d86981c84b88bbea627d30ff71b5ab1402636b366f73737817/marshmallow-2.8.0.tar.gz"; | |
|
841 | md5 = "204513fc123a3d9bdd7b63b9747f02e6"; | |
|
842 | }; | |
|
843 | meta = { | |
|
844 | license = [ pkgs.lib.licenses.mit ]; | |
|
845 | }; | |
|
846 | }; | |
|
834 | 847 | mccabe = super.buildPythonPackage { |
|
835 | 848 | name = "mccabe-0.3"; |
|
836 | 849 | buildInputs = with self; []; |
@@ -1355,7 +1368,7 b'' | |||
|
1355 | 1368 | name = "rhodecode-enterprise-ce-4.3.0"; |
|
1356 | 1369 | buildInputs = with self; [WebTest configobj cssselect flake8 lxml mock pytest pytest-cov pytest-runner]; |
|
1357 | 1370 | doCheck = true; |
|
1358 | propagatedBuildInputs = with self; [Babel Beaker FormEncode Mako Markdown MarkupSafe MySQL-python Paste PasteDeploy PasteScript Pygments Pylons Pyro4 Routes SQLAlchemy Tempita URLObject WebError WebHelpers WebHelpers2 WebOb WebTest Whoosh alembic amqplib anyjson appenlight-client authomatic backport-ipaddress celery colander decorator docutils gunicorn infrae.cache ipython iso8601 kombu msgpack-python packaging psycopg2 py-gfm pycrypto pycurl pyparsing pyramid pyramid-debugtoolbar pyramid-mako pyramid-beaker pysqlite python-dateutil python-ldap python-memcached python-pam recaptcha-client repoze.lru requests simplejson waitress zope.cachedescriptors dogpile.cache dogpile.core psutil py-bcrypt]; | |
|
1371 | propagatedBuildInputs = with self; [Babel Beaker FormEncode Mako Markdown MarkupSafe MySQL-python Paste PasteDeploy PasteScript Pygments Pylons Pyro4 Routes SQLAlchemy Tempita URLObject WebError WebHelpers WebHelpers2 WebOb WebTest Whoosh alembic amqplib anyjson appenlight-client authomatic backport-ipaddress celery colander decorator docutils gunicorn infrae.cache ipython iso8601 kombu marshmallow msgpack-python packaging psycopg2 py-gfm pycrypto pycurl pyparsing pyramid pyramid-debugtoolbar pyramid-mako pyramid-beaker pysqlite python-dateutil python-ldap python-memcached python-pam recaptcha-client repoze.lru requests simplejson waitress zope.cachedescriptors dogpile.cache dogpile.core psutil py-bcrypt]; | |
|
1359 | 1372 | src = ./.; |
|
1360 | 1373 | meta = { |
|
1361 | 1374 | license = [ { fullName = "AGPLv3, and Commercial License"; } ]; |
@@ -1637,5 +1650,5 b'' | |||
|
1637 | 1650 | |
|
1638 | 1651 | ### Test requirements |
|
1639 | 1652 | |
|
1640 | ||
|
1653 | ||
|
1641 | 1654 | } |
@@ -84,6 +84,7 b' iso8601==0.1.11' | |||
|
84 | 84 | itsdangerous==0.24 |
|
85 | 85 | kombu==1.5.1 |
|
86 | 86 | lxml==3.4.4 |
|
87 | marshmallow==2.8.0 | |
|
87 | 88 | mccabe==0.3 |
|
88 | 89 | meld3==1.0.2 |
|
89 | 90 | mock==1.0.1 |
@@ -47,9 +47,14 b' class TestApiUpdateRepo(object):' | |||
|
47 | 47 | ({'enable_statistics': True}, SAME_AS_UPDATES), |
|
48 | 48 | ({'enable_locking': True}, SAME_AS_UPDATES), |
|
49 | 49 | ({'enable_downloads': True}, SAME_AS_UPDATES), |
|
50 |
({'name': 'new_repo_name'}, { |
|
|
51 | ({'group': 'test_group_for_update'}, | |
|
52 | {'repo_name': 'test_group_for_update/%s' % UPDATE_REPO_NAME}), | |
|
50 | ({'name': 'new_repo_name'}, { | |
|
51 | 'repo_name': 'new_repo_name', | |
|
52 | 'url': 'http://test.example.com:80/new_repo_name', | |
|
53 | }), | |
|
54 | ({'group': 'test_group_for_update'}, { | |
|
55 | 'repo_name': 'test_group_for_update/%s' % UPDATE_REPO_NAME, | |
|
56 | 'url': 'http://test.example.com:80/test_group_for_update/%s' % UPDATE_REPO_NAME | |
|
57 | }), | |
|
53 | 58 | ]) |
|
54 | 59 | def test_api_update_repo(self, updates, expected, backend): |
|
55 | 60 | repo_name = UPDATE_REPO_NAME |
@@ -454,6 +454,7 b' class PullrequestsController(BaseRepoCon' | |||
|
454 | 454 | h.flash(_('Successfully opened new pull request'), |
|
455 | 455 | category='success') |
|
456 | 456 | except Exception as e: |
|
457 | raise | |
|
457 | 458 | msg = _('Error occurred during sending pull request') |
|
458 | 459 | log.exception(msg) |
|
459 | 460 | h.flash(msg, category='error') |
@@ -19,12 +19,6 b'' | |||
|
19 | 19 | from pyramid.threadlocal import get_current_registry |
|
20 | 20 | |
|
21 | 21 | |
|
22 | class RhodecodeEvent(object): | |
|
23 | """ | |
|
24 | Base event class for all Rhodecode events | |
|
25 | """ | |
|
26 | ||
|
27 | ||
|
28 | 22 | def trigger(event): |
|
29 | 23 | """ |
|
30 | 24 | Helper method to send an event. This wraps the pyramid logic to send an |
@@ -37,6 +31,8 b' def trigger(event):' | |||
|
37 | 31 | registry.notify(event) |
|
38 | 32 | |
|
39 | 33 | |
|
34 | from rhodecode.events.base import RhodecodeEvent | |
|
35 | ||
|
40 | 36 | from rhodecode.events.user import ( |
|
41 | 37 | UserPreCreate, |
|
42 | 38 | UserPreUpdate, |
@@ -44,6 +40,7 b' from rhodecode.events.user import (' | |||
|
44 | 40 | ) |
|
45 | 41 | |
|
46 | 42 | from rhodecode.events.repo import ( |
|
43 | RepoEvent, | |
|
47 | 44 | RepoPreCreateEvent, RepoCreatedEvent, |
|
48 | 45 | RepoPreDeleteEvent, RepoDeletedEvent, |
|
49 | 46 | RepoPrePushEvent, RepoPushEvent, |
@@ -51,6 +48,7 b' from rhodecode.events.repo import (' | |||
|
51 | 48 | ) |
|
52 | 49 | |
|
53 | 50 | from rhodecode.events.pullrequest import ( |
|
51 | PullRequestEvent, | |
|
54 | 52 | PullRequestCreateEvent, |
|
55 | 53 | PullRequestUpdateEvent, |
|
56 | 54 | PullRequestReviewEvent, |
@@ -16,15 +16,40 b'' | |||
|
16 | 16 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | 17 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | 18 | |
|
19 | from marshmallow import Schema, fields | |
|
20 | ||
|
19 | 21 | from rhodecode.events.repo import RepoEvent |
|
20 | 22 | |
|
21 | 23 | |
|
24 | def get_pull_request_url(pull_request): | |
|
25 | from rhodecode.model.pull_request import PullRequestModel | |
|
26 | return PullRequestModel().get_url(pull_request) | |
|
27 | ||
|
28 | ||
|
29 | class PullRequestSchema(Schema): | |
|
30 | """ | |
|
31 | Marshmallow schema for a pull request | |
|
32 | """ | |
|
33 | pull_request_id = fields.Integer() | |
|
34 | url = fields.Function(get_pull_request_url) | |
|
35 | title = fields.Str() | |
|
36 | ||
|
37 | ||
|
38 | class PullRequestEventSchema(RepoEvent.MarshmallowSchema): | |
|
39 | """ | |
|
40 | Marshmallow schema for a pull request event | |
|
41 | """ | |
|
42 | pullrequest = fields.Nested(PullRequestSchema) | |
|
43 | ||
|
44 | ||
|
22 | 45 | class PullRequestEvent(RepoEvent): |
|
23 | 46 | """ |
|
24 | Base class for events acting on a repository. | |
|
47 | Base class for pull request events. | |
|
25 | 48 | |
|
26 |
:param |
|
|
49 | :param pullrequest: a :class:`PullRequest` instance | |
|
27 | 50 | """ |
|
51 | MarshmallowSchema = PullRequestEventSchema | |
|
52 | ||
|
28 | 53 | def __init__(self, pullrequest): |
|
29 | 54 | super(PullRequestEvent, self).__init__(pullrequest.target_repo) |
|
30 | 55 | self.pullrequest = pullrequest |
@@ -16,8 +16,31 b'' | |||
|
16 | 16 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
17 | 17 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | 18 | |
|
19 | from marshmallow import Schema, fields | |
|
20 | ||
|
19 | 21 | from rhodecode.model.db import Repository, Session |
|
20 | from rhodecode.events import RhodecodeEvent | |
|
22 | from rhodecode.events.base import RhodecodeEvent | |
|
23 | ||
|
24 | ||
|
25 | def get_pull_request_url(repo): | |
|
26 | from rhodecode.model.repo import RepoModel | |
|
27 | return RepoModel().get_url(repo) | |
|
28 | ||
|
29 | ||
|
30 | class RepositorySchema(Schema): | |
|
31 | """ | |
|
32 | Marshmallow schema for a repository | |
|
33 | """ | |
|
34 | repo_id = fields.Integer() | |
|
35 | repo_name = fields.Str() | |
|
36 | url = fields.Function(get_pull_request_url) | |
|
37 | ||
|
38 | ||
|
39 | class RepoEventSchema(RhodecodeEvent.MarshmallowSchema): | |
|
40 | """ | |
|
41 | Marshmallow schema for a repository event | |
|
42 | """ | |
|
43 | repository = fields.Nested(RepositorySchema) | |
|
21 | 44 | |
|
22 | 45 | |
|
23 | 46 | class RepoEvent(RhodecodeEvent): |
@@ -26,7 +49,10 b' class RepoEvent(RhodecodeEvent):' | |||
|
26 | 49 | |
|
27 | 50 | :param repo: a :class:`Repository` instance |
|
28 | 51 | """ |
|
52 | MarshmallowSchema = RepoEventSchema | |
|
53 | ||
|
29 | 54 | def __init__(self, repo): |
|
55 | super(RepoEvent, self).__init__() | |
|
30 | 56 | self.repo = repo |
|
31 | 57 | |
|
32 | 58 | |
@@ -73,6 +99,16 b' class RepoVCSEvent(RepoEvent):' | |||
|
73 | 99 | self.extras = extras |
|
74 | 100 | super(RepoVCSEvent, self).__init__(self.repo) |
|
75 | 101 | |
|
102 | @property | |
|
103 | def acting_user(self): | |
|
104 | if self.extras.get('username'): | |
|
105 | return User.get_by_username(extras['username']) | |
|
106 | ||
|
107 | @property | |
|
108 | def acting_ip(self): | |
|
109 | if self.extras.get('ip'): | |
|
110 | return User.get_by_username(extras['ip']) | |
|
111 | ||
|
76 | 112 | |
|
77 | 113 | class RepoPrePullEvent(RepoVCSEvent): |
|
78 | 114 | """ |
@@ -17,7 +17,8 b'' | |||
|
17 | 17 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
18 | 18 | |
|
19 | 19 | from zope.interface import implementer |
|
20 | from rhodecode.events import RhodecodeEvent | |
|
20 | ||
|
21 | from rhodecode.events.base import RhodecodeEvent | |
|
21 | 22 | from rhodecode.events.interfaces import ( |
|
22 | 23 | IUserRegistered, IUserPreCreate, IUserPreUpdate) |
|
23 | 24 |
@@ -1641,6 +1641,7 b' class Repository(Base, BaseModel):' | |||
|
1641 | 1641 | 'repo_name': repo.repo_name, |
|
1642 | 1642 | 'repo_type': repo.repo_type, |
|
1643 | 1643 | 'clone_uri': repo.clone_uri or '', |
|
1644 | 'url': url('summary_home', repo_name=self.repo_name, qualified=True), | |
|
1644 | 1645 | 'private': repo.private, |
|
1645 | 1646 | 'created_on': repo.created_on, |
|
1646 | 1647 | 'description': repo.description, |
@@ -3112,10 +3113,9 b' class PullRequest(Base, _PullRequestBase' | |||
|
3112 | 3113 | merge_status = PullRequestModel().merge_status(pull_request) |
|
3113 | 3114 | data = { |
|
3114 | 3115 | 'pull_request_id': pull_request.pull_request_id, |
|
3115 | 'url': url('pullrequest_show', | |
|
3116 | repo_name=pull_request.target_repo.repo_name, | |
|
3117 | pull_request_id=pull_request.pull_request_id, | |
|
3118 | qualified=True), | |
|
3116 | 'url': url('pullrequest_show', repo_name=self.target_repo.repo_name, | |
|
3117 | pull_request_id=self.pull_request_id, | |
|
3118 | qualified=True), | |
|
3119 | 3119 | 'title': pull_request.title, |
|
3120 | 3120 | 'description': pull_request.description, |
|
3121 | 3121 | 'status': pull_request.status, |
@@ -748,6 +748,11 b' class PullRequestModel(BaseModel):' | |||
|
748 | 748 | |
|
749 | 749 | return ids_to_add, ids_to_remove |
|
750 | 750 | |
|
751 | def get_url(self, pull_request): | |
|
752 | return url('pullrequest_show', repo_name=self.target_repo.repo_name, | |
|
753 | pull_request_id=self.pull_request_id, | |
|
754 | qualified=True) | |
|
755 | ||
|
751 | 756 | def notify_reviewers(self, pull_request, reviewers_ids): |
|
752 | 757 | # notification to reviewers |
|
753 | 758 | if not reviewers_ids: |
@@ -141,6 +141,9 b' class RepoModel(BaseModel):' | |||
|
141 | 141 | |
|
142 | 142 | return None |
|
143 | 143 | |
|
144 | def get_url(self, repo): | |
|
145 | return url('summary_home', repo_name=repo.repo_name, qualified=True) | |
|
146 | ||
|
144 | 147 | def get_users(self, name_contains=None, limit=20, only_active=True): |
|
145 | 148 | # TODO: mikhail: move this method to the UserModel. |
|
146 | 149 | query = self.sa.query(User) |
General Comments 0
You need to be logged in to leave comments.
Login now