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 | license = [ pkgs.lib.licenses.bsdOriginal ]; |
|
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 | mccabe = super.buildPythonPackage { |
|
847 | mccabe = super.buildPythonPackage { | |
835 | name = "mccabe-0.3"; |
|
848 | name = "mccabe-0.3"; | |
836 | buildInputs = with self; []; |
|
849 | buildInputs = with self; []; | |
@@ -1355,7 +1368,7 b'' | |||||
1355 | name = "rhodecode-enterprise-ce-4.3.0"; |
|
1368 | name = "rhodecode-enterprise-ce-4.3.0"; | |
1356 | buildInputs = with self; [WebTest configobj cssselect flake8 lxml mock pytest pytest-cov pytest-runner]; |
|
1369 | buildInputs = with self; [WebTest configobj cssselect flake8 lxml mock pytest pytest-cov pytest-runner]; | |
1357 | doCheck = true; |
|
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 | src = ./.; |
|
1372 | src = ./.; | |
1360 | meta = { |
|
1373 | meta = { | |
1361 | license = [ { fullName = "AGPLv3, and Commercial License"; } ]; |
|
1374 | license = [ { fullName = "AGPLv3, and Commercial License"; } ]; |
@@ -84,6 +84,7 b' iso8601==0.1.11' | |||||
84 | itsdangerous==0.24 |
|
84 | itsdangerous==0.24 | |
85 | kombu==1.5.1 |
|
85 | kombu==1.5.1 | |
86 | lxml==3.4.4 |
|
86 | lxml==3.4.4 | |
|
87 | marshmallow==2.8.0 | |||
87 | mccabe==0.3 |
|
88 | mccabe==0.3 | |
88 | meld3==1.0.2 |
|
89 | meld3==1.0.2 | |
89 | mock==1.0.1 |
|
90 | mock==1.0.1 |
@@ -47,9 +47,14 b' class TestApiUpdateRepo(object):' | |||||
47 | ({'enable_statistics': True}, SAME_AS_UPDATES), |
|
47 | ({'enable_statistics': True}, SAME_AS_UPDATES), | |
48 | ({'enable_locking': True}, SAME_AS_UPDATES), |
|
48 | ({'enable_locking': True}, SAME_AS_UPDATES), | |
49 | ({'enable_downloads': True}, SAME_AS_UPDATES), |
|
49 | ({'enable_downloads': True}, SAME_AS_UPDATES), | |
50 |
({'name': 'new_repo_name'}, { |
|
50 | ({'name': 'new_repo_name'}, { | |
51 | ({'group': 'test_group_for_update'}, |
|
51 | 'repo_name': 'new_repo_name', | |
52 | {'repo_name': 'test_group_for_update/%s' % UPDATE_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 | def test_api_update_repo(self, updates, expected, backend): |
|
59 | def test_api_update_repo(self, updates, expected, backend): | |
55 | repo_name = UPDATE_REPO_NAME |
|
60 | repo_name = UPDATE_REPO_NAME |
@@ -454,6 +454,7 b' class PullrequestsController(BaseRepoCon' | |||||
454 | h.flash(_('Successfully opened new pull request'), |
|
454 | h.flash(_('Successfully opened new pull request'), | |
455 | category='success') |
|
455 | category='success') | |
456 | except Exception as e: |
|
456 | except Exception as e: | |
|
457 | raise | |||
457 | msg = _('Error occurred during sending pull request') |
|
458 | msg = _('Error occurred during sending pull request') | |
458 | log.exception(msg) |
|
459 | log.exception(msg) | |
459 | h.flash(msg, category='error') |
|
460 | h.flash(msg, category='error') |
@@ -19,12 +19,6 b'' | |||||
19 | from pyramid.threadlocal import get_current_registry |
|
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 | def trigger(event): |
|
22 | def trigger(event): | |
29 | """ |
|
23 | """ | |
30 | Helper method to send an event. This wraps the pyramid logic to send an |
|
24 | Helper method to send an event. This wraps the pyramid logic to send an | |
@@ -37,6 +31,8 b' def trigger(event):' | |||||
37 | registry.notify(event) |
|
31 | registry.notify(event) | |
38 |
|
32 | |||
39 |
|
33 | |||
|
34 | from rhodecode.events.base import RhodecodeEvent | |||
|
35 | ||||
40 | from rhodecode.events.user import ( |
|
36 | from rhodecode.events.user import ( | |
41 | UserPreCreate, |
|
37 | UserPreCreate, | |
42 | UserPreUpdate, |
|
38 | UserPreUpdate, | |
@@ -44,6 +40,7 b' from rhodecode.events.user import (' | |||||
44 | ) |
|
40 | ) | |
45 |
|
41 | |||
46 | from rhodecode.events.repo import ( |
|
42 | from rhodecode.events.repo import ( | |
|
43 | RepoEvent, | |||
47 | RepoPreCreateEvent, RepoCreatedEvent, |
|
44 | RepoPreCreateEvent, RepoCreatedEvent, | |
48 | RepoPreDeleteEvent, RepoDeletedEvent, |
|
45 | RepoPreDeleteEvent, RepoDeletedEvent, | |
49 | RepoPrePushEvent, RepoPushEvent, |
|
46 | RepoPrePushEvent, RepoPushEvent, | |
@@ -51,6 +48,7 b' from rhodecode.events.repo import (' | |||||
51 | ) |
|
48 | ) | |
52 |
|
49 | |||
53 | from rhodecode.events.pullrequest import ( |
|
50 | from rhodecode.events.pullrequest import ( | |
|
51 | PullRequestEvent, | |||
54 | PullRequestCreateEvent, |
|
52 | PullRequestCreateEvent, | |
55 | PullRequestUpdateEvent, |
|
53 | PullRequestUpdateEvent, | |
56 | PullRequestReviewEvent, |
|
54 | PullRequestReviewEvent, |
@@ -16,15 +16,40 b'' | |||||
16 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
16 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
17 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
17 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
18 |
|
18 | |||
|
19 | from marshmallow import Schema, fields | |||
|
20 | ||||
19 | from rhodecode.events.repo import RepoEvent |
|
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 | class PullRequestEvent(RepoEvent): |
|
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 | def __init__(self, pullrequest): |
|
53 | def __init__(self, pullrequest): | |
29 | super(PullRequestEvent, self).__init__(pullrequest.target_repo) |
|
54 | super(PullRequestEvent, self).__init__(pullrequest.target_repo) | |
30 | self.pullrequest = pullrequest |
|
55 | self.pullrequest = pullrequest |
@@ -16,8 +16,31 b'' | |||||
16 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
16 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
17 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
17 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
18 |
|
18 | |||
|
19 | from marshmallow import Schema, fields | |||
|
20 | ||||
19 | from rhodecode.model.db import Repository, Session |
|
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 | class RepoEvent(RhodecodeEvent): |
|
46 | class RepoEvent(RhodecodeEvent): | |
@@ -26,7 +49,10 b' class RepoEvent(RhodecodeEvent):' | |||||
26 |
|
49 | |||
27 | :param repo: a :class:`Repository` instance |
|
50 | :param repo: a :class:`Repository` instance | |
28 | """ |
|
51 | """ | |
|
52 | MarshmallowSchema = RepoEventSchema | |||
|
53 | ||||
29 | def __init__(self, repo): |
|
54 | def __init__(self, repo): | |
|
55 | super(RepoEvent, self).__init__() | |||
30 | self.repo = repo |
|
56 | self.repo = repo | |
31 |
|
57 | |||
32 |
|
58 | |||
@@ -73,6 +99,16 b' class RepoVCSEvent(RepoEvent):' | |||||
73 | self.extras = extras |
|
99 | self.extras = extras | |
74 | super(RepoVCSEvent, self).__init__(self.repo) |
|
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 | class RepoPrePullEvent(RepoVCSEvent): |
|
113 | class RepoPrePullEvent(RepoVCSEvent): | |
78 | """ |
|
114 | """ |
@@ -17,7 +17,8 b'' | |||||
17 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
17 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
18 |
|
18 | |||
19 | from zope.interface import implementer |
|
19 | from zope.interface import implementer | |
20 | from rhodecode.events import RhodecodeEvent |
|
20 | ||
|
21 | from rhodecode.events.base import RhodecodeEvent | |||
21 | from rhodecode.events.interfaces import ( |
|
22 | from rhodecode.events.interfaces import ( | |
22 | IUserRegistered, IUserPreCreate, IUserPreUpdate) |
|
23 | IUserRegistered, IUserPreCreate, IUserPreUpdate) | |
23 |
|
24 |
@@ -1641,6 +1641,7 b' class Repository(Base, BaseModel):' | |||||
1641 | 'repo_name': repo.repo_name, |
|
1641 | 'repo_name': repo.repo_name, | |
1642 | 'repo_type': repo.repo_type, |
|
1642 | 'repo_type': repo.repo_type, | |
1643 | 'clone_uri': repo.clone_uri or '', |
|
1643 | 'clone_uri': repo.clone_uri or '', | |
|
1644 | 'url': url('summary_home', repo_name=self.repo_name, qualified=True), | |||
1644 | 'private': repo.private, |
|
1645 | 'private': repo.private, | |
1645 | 'created_on': repo.created_on, |
|
1646 | 'created_on': repo.created_on, | |
1646 | 'description': repo.description, |
|
1647 | 'description': repo.description, | |
@@ -3112,9 +3113,8 b' class PullRequest(Base, _PullRequestBase' | |||||
3112 | merge_status = PullRequestModel().merge_status(pull_request) |
|
3113 | merge_status = PullRequestModel().merge_status(pull_request) | |
3113 | data = { |
|
3114 | data = { | |
3114 | 'pull_request_id': pull_request.pull_request_id, |
|
3115 | 'pull_request_id': pull_request.pull_request_id, | |
3115 | 'url': url('pullrequest_show', |
|
3116 | 'url': url('pullrequest_show', repo_name=self.target_repo.repo_name, | |
3116 | repo_name=pull_request.target_repo.repo_name, |
|
3117 | pull_request_id=self.pull_request_id, | |
3117 | pull_request_id=pull_request.pull_request_id, |
|
|||
3118 | qualified=True), |
|
3118 | qualified=True), | |
3119 | 'title': pull_request.title, |
|
3119 | 'title': pull_request.title, | |
3120 | 'description': pull_request.description, |
|
3120 | 'description': pull_request.description, |
@@ -748,6 +748,11 b' class PullRequestModel(BaseModel):' | |||||
748 |
|
748 | |||
749 | return ids_to_add, ids_to_remove |
|
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 | def notify_reviewers(self, pull_request, reviewers_ids): |
|
756 | def notify_reviewers(self, pull_request, reviewers_ids): | |
752 | # notification to reviewers |
|
757 | # notification to reviewers | |
753 | if not reviewers_ids: |
|
758 | if not reviewers_ids: |
@@ -141,6 +141,9 b' class RepoModel(BaseModel):' | |||||
141 |
|
141 | |||
142 | return None |
|
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 | def get_users(self, name_contains=None, limit=20, only_active=True): |
|
147 | def get_users(self, name_contains=None, limit=20, only_active=True): | |
145 | # TODO: mikhail: move this method to the UserModel. |
|
148 | # TODO: mikhail: move this method to the UserModel. | |
146 | query = self.sa.query(User) |
|
149 | query = self.sa.query(User) |
General Comments 0
You need to be logged in to leave comments.
Login now