##// END OF EJS Templates
feat(events): added context into events so we can track additional context of calling it
super-admin -
r5623:2f80d511 default
parent child Browse files
Show More
@@ -1,88 +1,91 b''
1 1 # Copyright (C) 2016-2024 RhodeCode GmbH
2 2 #
3 3 # This program is free software: you can redistribute it and/or modify
4 4 # it under the terms of the GNU Affero General Public License, version 3
5 5 # (only), as published by the Free Software Foundation.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU Affero General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 #
15 15 # This program is dual-licensed. If you wish to learn more about the
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 19 import logging
20 20
21 from rhodecode.events.base import (
22 RhodeCodeIntegrationEvent,
23 RhodecodeEvent
24 )
21 from rhodecode.events.base import RhodeCodeIntegrationEvent, RhodecodeEvent
25 22
26 23 from rhodecode.events.base import ( # pragma: no cover
27 FtsBuild
24 FtsBuild,
28 25 )
29 26
30 27 from rhodecode.events.user import ( # pragma: no cover
31 28 UserPreCreate,
32 29 UserPostCreate,
33 30 UserPreUpdate,
34 31 UserRegistered,
35 32 UserPermissionsChange,
36 33 )
37 34
38 35 from rhodecode.events.repo import ( # pragma: no cover
39 36 RepoEvent,
40 RepoCommitCommentEvent, RepoCommitCommentEditEvent,
41 RepoPreCreateEvent, RepoCreateEvent,
42 RepoPreDeleteEvent, RepoDeleteEvent,
43 RepoPrePushEvent, RepoPushEvent,
44 RepoPrePullEvent, RepoPullEvent,
37 RepoCommitCommentEvent,
38 RepoCommitCommentEditEvent,
39 RepoPreCreateEvent,
40 RepoCreateEvent,
41 RepoPreDeleteEvent,
42 RepoDeleteEvent,
43 RepoPrePushEvent,
44 RepoPushEvent,
45 RepoPrePullEvent,
46 RepoPullEvent,
45 47 )
46 48
47 49 from rhodecode.events.repo_group import ( # pragma: no cover
48 50 RepoGroupEvent,
49 51 RepoGroupCreateEvent,
50 52 RepoGroupUpdateEvent,
51 53 RepoGroupDeleteEvent,
52 54 )
53 55
54 56 from rhodecode.events.pullrequest import ( # pragma: no cover
55 57 PullRequestEvent,
56 58 PullRequestCreateEvent,
57 59 PullRequestUpdateEvent,
58 60 PullRequestCommentEvent,
59 61 PullRequestCommentEditEvent,
60 62 PullRequestReviewEvent,
61 63 PullRequestMergeEvent,
62 64 PullRequestCloseEvent,
63 65 )
64 66
65 67
66 68 log = logging.getLogger(__name__)
67 69
68 70
69 71 def trigger(event, registry=None):
70 72 """
71 73 Helper method to send an event. This wraps the pyramid logic to send an
72 74 event.
73 75 """
74 76 # For the first step we are using pyramids thread locals here. If the
75 77 # event mechanism works out as a good solution we should think about
76 78 # passing the registry as an argument to get rid of it.
77 79 from pyramid.threadlocal import get_current_registry
78 80
79 81 event_name = event.__class__
80 log.debug('event %s sent for execution', event_name)
82 log.debug("event %s sent for execution", event_name)
81 83 registry = registry or get_current_registry()
82 84 registry.notify(event)
83 log.debug('event %s triggered using registry %s', event_name, registry)
85 log.debug("event %s triggered using registry %s", event_name, registry)
84 86
85 87 # Send the events to integrations directly
86 88 from rhodecode.integrations import integrations_event_handler
89
87 90 if isinstance(event, RhodeCodeIntegrationEvent):
88 91 integrations_event_handler(event)
@@ -1,141 +1,140 b''
1 1 # Copyright (C) 2016-2024 RhodeCode GmbH
2 2 #
3 3 # This program is free software: you can redistribute it and/or modify
4 4 # it under the terms of the GNU Affero General Public License, version 3
5 5 # (only), as published by the Free Software Foundation.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU Affero General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 #
15 15 # This program is dual-licensed. If you wish to learn more about the
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 19 import logging
20 20 import datetime
21 21
22 22 from zope.cachedescriptors.property import Lazy as LazyProperty
23 23
24 24 from rhodecode.lib.pyramid_utils import get_current_request
25 25 from rhodecode.lib.utils2 import AttributeDict
26 26
27 27
28 28 # this is a user object to be used for events caused by the system (eg. shell)
29 SYSTEM_USER = AttributeDict(dict(
30 username='__SYSTEM__',
31 user_id='__SYSTEM_ID__'
32 ))
29 SYSTEM_USER = AttributeDict(dict(username="__SYSTEM__", user_id="__SYSTEM_ID__"))
33 30
34 31 log = logging.getLogger(__name__)
35 32
36 33
37 34 class RhodecodeEvent(object):
38 35 """
39 36 Base event class for all RhodeCode events
40 37 """
38
41 39 name = "RhodeCodeEvent"
42 no_url_set = '<no server_url available>'
40 no_url_set = "<no server_url available>"
43 41
44 def __init__(self, request=None, actor=None):
42 def __init__(self, request=None, actor=None, context=None):
45 43 self._request = request
46 44 self._actor = actor
45 self._context = context
47 46 self.utc_timestamp = datetime.datetime.utcnow()
48 47
49 48 def __repr__(self):
50 return '<{}:({})>'.format(self.__class__.__name__, self.name)
49 return f"<{self.__class__.__name__}:(name={self.name}, context={self._context})>"
51 50
52 51 def get_request(self):
53 52 if self._request:
54 53 return self._request
55 54 return get_current_request()
56 55
57 56 @LazyProperty
58 57 def request(self):
59 58 return self.get_request()
60 59
61 60 @property
62 61 def auth_user(self):
63 62 if not self.request:
64 63 return
65 64
66 user = getattr(self.request, 'user', None)
65 user = getattr(self.request, "user", None)
67 66 if user:
68 67 return user
69 68
70 api_user = getattr(self.request, 'rpc_user', None)
69 api_user = getattr(self.request, "rpc_user", None)
71 70 if api_user:
72 71 return api_user
73 72
74 73 @property
75 74 def actor(self):
76 75 from rhodecode.lib.auth import AuthUser
77 76
78 77 # if an explicit actor is specified, use this
79 78 if self._actor:
80 79 return self._actor
81 80
82 81 auth_user = self.auth_user
83 log.debug('Got integration actor: %s', auth_user)
82 log.debug("Got integration actor: %s", auth_user)
84 83 if isinstance(auth_user, AuthUser):
85 84 instance = auth_user.get_instance()
86 85 # we can't find this DB user...
87 86 if not instance:
88 return AttributeDict(dict(
87 return AttributeDict(
88 dict(
89 89 username=auth_user.username,
90 90 user_id=auth_user.user_id,
91 ))
91 )
92 )
92 93 elif auth_user:
93 94 return auth_user
94 95 return SYSTEM_USER
95 96
96 97 @property
97 98 def actor_ip(self):
98 99 auth_user = self.auth_user
99 100 if auth_user:
100 101 return auth_user.ip_addr
101 return '<no ip available>'
102 return "<no ip available>"
102 103
103 104 @property
104 105 def server_url(self):
105 106 if self.request:
106 107 try:
107 return self.request.route_url('home')
108 return self.request.route_url("home")
108 109 except Exception:
109 log.exception('Failed to fetch URL for server')
110 log.exception("Failed to fetch URL for server")
110 111 return self.no_url_set
111 112
112 113 return self.no_url_set
113 114
114 115 def as_dict(self):
115 116 data = {
116 'name': self.name,
117 'utc_timestamp': self.utc_timestamp,
118 'actor_ip': self.actor_ip,
119 'actor': {
120 'username': self.actor.username,
121 'user_id': self.actor.user_id
122 },
123 'server_url': self.server_url
117 "name": self.name,
118 "utc_timestamp": self.utc_timestamp,
119 "actor_ip": self.actor_ip,
120 "actor": {"username": self.actor.username, "user_id": self.actor.user_id},
121 "server_url": self.server_url,
124 122 }
125 123 return data
126 124
127 125
128 126 class RhodeCodeIntegrationEvent(RhodecodeEvent):
129 127 """
130 128 Special subclass for Integration events
131 129 """
132 description = ''
130
131 description = ""
133 132
134 133
135 134 class FtsBuild(RhodecodeEvent):
136 135 """
137 136 This event will be triggered when FTS Build is triggered
138 137 """
139 name = 'fts-build'
140 display_name = 'Start FTS Build'
141 138
139 name = "fts-build"
140 display_name = "Start FTS Build"
@@ -1,43 +1,46 b''
1 1 # Copyright (C) 2016-2024 RhodeCode GmbH
2 2 #
3 3 # This program is free software: you can redistribute it and/or modify
4 4 # it under the terms of the GNU Affero General Public License, version 3
5 5 # (only), as published by the Free Software Foundation.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU Affero General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 #
15 15 # This program is dual-licensed. If you wish to learn more about the
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 19 from zope.interface import Attribute, Interface
20 20
21 21
22 22 class IUserRegistered(Interface):
23 23 """
24 24 An event type that is emitted whenever a new user registers a user
25 25 account.
26 26 """
27 user = Attribute('The user object.')
28 session = Attribute('The session while processing the register form post.')
27
28 user = Attribute("The user object.")
29 session = Attribute("The session while processing the register form post.")
29 30
30 31
31 32 class IUserPreCreate(Interface):
32 33 """
33 34 An event type that is emitted before a new user object is created.
34 35 """
35 user_data = Attribute('Data used to create the new user')
36
37 user_data = Attribute("Data used to create the new user")
36 38
37 39
38 40 class IUserPreUpdate(Interface):
39 41 """
40 42 An event type that is emitted before a user object is updated.
41 43 """
42 user = Attribute('The not yet updated user object')
43 user_data = Attribute('Data used to update the user')
44
45 user = Attribute("The not yet updated user object")
46 user_data = Attribute("Data used to update the user")
@@ -1,206 +1,212 b''
1 1 # Copyright (C) 2016-2024 RhodeCode GmbH
2 2 #
3 3 # This program is free software: you can redistribute it and/or modify
4 4 # it under the terms of the GNU Affero General Public License, version 3
5 5 # (only), as published by the Free Software Foundation.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU Affero General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 #
15 15 # This program is dual-licensed. If you wish to learn more about the
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 19 import logging
20 20
21 21 from rhodecode.translation import lazy_ugettext
22 from rhodecode.events.repo import (RepoEvent, _commits_as_dict, _issues_as_dict)
22 from rhodecode.events.repo import RepoEvent, _commits_as_dict, _issues_as_dict
23 23
24 24 log = logging.getLogger(__name__)
25 25
26 26
27 27 class PullRequestEvent(RepoEvent):
28 28 """
29 29 Base class for pull request events.
30 30
31 31 :param pullrequest: a :class:`PullRequest` instance
32 32 """
33 name = 'pullrequest-event'
34 display_name = lazy_ugettext('pullrequest generic event')
35 description = lazy_ugettext('All events within a context of a pull request')
33
34 name = "pullrequest-event"
35 display_name = lazy_ugettext("pullrequest generic event")
36 description = lazy_ugettext("All events within a context of a pull request")
36 37
37 def __init__(self, pullrequest):
38 super().__init__(pullrequest.target_repo)
38 def __init__(self, pullrequest, context=None):
39 super().__init__(pullrequest.target_repo, context=context)
39 40 self.pullrequest = pullrequest
41 self.context = self._context
40 42
41 43 def as_dict(self):
42 44 from rhodecode.lib.utils2 import md5_safe
43 45 from rhodecode.model.pull_request import PullRequestModel
46
44 47 data = super().as_dict()
45 48
46 commits = _commits_as_dict(
47 self,
48 commit_ids=self.pullrequest.revisions,
49 repos=[self.pullrequest.source_repo]
50 )
49 commits = _commits_as_dict(self, commit_ids=self.pullrequest.revisions, repos=[self.pullrequest.source_repo])
51 50 issues = _issues_as_dict(commits)
52 51 # calculate hashes of all commits for unique identifier of commits
53 52 # inside that pull request
54 commits_hash = md5_safe(':'.join(x.get('raw_id', '') for x in commits))
53 commits_hash = md5_safe(":".join(x.get("raw_id", "") for x in commits))
55 54
56 data.update({
57 'pullrequest': {
58 'title': self.pullrequest.title,
59 'issues': issues,
60 'pull_request_id': self.pullrequest.pull_request_id,
61 'url': PullRequestModel().get_url(
62 self.pullrequest, request=self.request),
63 'permalink_url': PullRequestModel().get_url(
64 self.pullrequest, request=self.request, permalink=True),
65 'shadow_url': PullRequestModel().get_shadow_clone_url(
66 self.pullrequest, request=self.request),
67 'status': self.pullrequest.calculated_review_status(),
68 'commits_uid': commits_hash,
69 'commits': commits,
55 data.update(
56 {
57 "pullrequest": {
58 "title": self.pullrequest.title,
59 "issues": issues,
60 "pull_request_id": self.pullrequest.pull_request_id,
61 "url": PullRequestModel().get_url(self.pullrequest, request=self.request),
62 "permalink_url": PullRequestModel().get_url(self.pullrequest, request=self.request, permalink=True),
63 "shadow_url": PullRequestModel().get_shadow_clone_url(self.pullrequest, request=self.request),
64 "status": self.pullrequest.calculated_review_status(),
65 "commits_uid": commits_hash,
66 "commits": commits,
67 },
68 "context": self.context,
70 69 }
71 })
70 )
72 71 return data
73 72
74 73
75 74 class PullRequestCreateEvent(PullRequestEvent):
76 75 """
77 76 An instance of this class is emitted as an :term:`event` after a pull
78 77 request is created.
79 78 """
80 name = 'pullrequest-create'
81 display_name = lazy_ugettext('pullrequest created')
82 description = lazy_ugettext('Event triggered after pull request was created')
79
80 name = "pullrequest-create"
81 display_name = lazy_ugettext("pullrequest created")
82 description = lazy_ugettext("Event triggered after pull request was created")
83 83
84 84
85 85 class PullRequestCloseEvent(PullRequestEvent):
86 86 """
87 87 An instance of this class is emitted as an :term:`event` after a pull
88 88 request is closed.
89 89 """
90 name = 'pullrequest-close'
91 display_name = lazy_ugettext('pullrequest closed')
92 description = lazy_ugettext('Event triggered after pull request was closed')
90
91 name = "pullrequest-close"
92 display_name = lazy_ugettext("pullrequest closed")
93 description = lazy_ugettext("Event triggered after pull request was closed")
93 94
94 95
95 96 class PullRequestUpdateEvent(PullRequestEvent):
96 97 """
97 98 An instance of this class is emitted as an :term:`event` after a pull
98 99 request's commits have been updated.
99 100 """
100 name = 'pullrequest-update'
101 display_name = lazy_ugettext('pullrequest commits updated')
102 description = lazy_ugettext('Event triggered after pull requests was updated')
101
102 name = "pullrequest-update"
103 display_name = lazy_ugettext("pullrequest commits updated")
104 description = lazy_ugettext("Event triggered after pull requests was updated")
103 105
104 106
105 107 class PullRequestReviewEvent(PullRequestEvent):
106 108 """
107 109 An instance of this class is emitted as an :term:`event` after a pull
108 110 request review has changed. A status defines new status of review.
109 111 """
110 name = 'pullrequest-review'
111 display_name = lazy_ugettext('pullrequest review changed')
112 description = lazy_ugettext('Event triggered after a review status of a '
113 'pull requests has changed to other.')
114 112
115 def __init__(self, pullrequest, status):
116 super().__init__(pullrequest)
113 name = "pullrequest-review"
114 display_name = lazy_ugettext("pullrequest review changed")
115 description = lazy_ugettext("Event triggered after a review status of a pull requests has changed to other.")
116
117 def __init__(self, pullrequest, status, context=None):
118 super().__init__(pullrequest, context=context)
117 119 self.status = status
118 120
119 121
120 122 class PullRequestMergeEvent(PullRequestEvent):
121 123 """
122 124 An instance of this class is emitted as an :term:`event` after a pull
123 125 request is merged.
124 126 """
125 name = 'pullrequest-merge'
126 display_name = lazy_ugettext('pullrequest merged')
127 description = lazy_ugettext('Event triggered after a successful merge operation '
128 'was executed on a pull request')
127
128 name = "pullrequest-merge"
129 display_name = lazy_ugettext("pullrequest merged")
130 description = lazy_ugettext("Event triggered after a successful merge operation was executed on a pull request")
129 131
130 132
131 133 class PullRequestCommentEvent(PullRequestEvent):
132 134 """
133 135 An instance of this class is emitted as an :term:`event` after a pull
134 136 request comment is created.
135 137 """
136 name = 'pullrequest-comment'
137 display_name = lazy_ugettext('pullrequest commented')
138 description = lazy_ugettext('Event triggered after a comment was made on a code '
139 'in the pull request')
140 138
141 def __init__(self, pullrequest, comment):
142 super().__init__(pullrequest)
139 name = "pullrequest-comment"
140 display_name = lazy_ugettext("pullrequest commented")
141 description = lazy_ugettext("Event triggered after a comment was made on a code in the pull request")
142
143 def __init__(self, pullrequest, comment, context=None):
144 super().__init__(pullrequest, context=context)
143 145 self.comment = comment
144 146
145 147 def as_dict(self):
146 148 from rhodecode.model.comment import CommentsModel
149
147 150 data = super().as_dict()
148 151
149 152 status = None
150 153 if self.comment.status_change:
151 154 status = self.comment.review_status
152 155
153 data.update({
154 'comment': {
155 'status': status,
156 'text': self.comment.text,
157 'type': self.comment.comment_type,
158 'file': self.comment.f_path,
159 'line': self.comment.line_no,
160 'version': self.comment.last_version,
161 'url': CommentsModel().get_url(
162 self.comment, request=self.request),
163 'permalink_url': CommentsModel().get_url(
164 self.comment, request=self.request, permalink=True),
156 data.update(
157 {
158 "comment": {
159 "status": status,
160 "text": self.comment.text,
161 "type": self.comment.comment_type,
162 "file": self.comment.f_path,
163 "line": self.comment.line_no,
164 "version": self.comment.last_version,
165 "url": CommentsModel().get_url(self.comment, request=self.request),
166 "permalink_url": CommentsModel().get_url(self.comment, request=self.request, permalink=True),
167 },
168 "context": self.context,
165 169 }
166 })
170 )
167 171 return data
168 172
169 173
170 174 class PullRequestCommentEditEvent(PullRequestEvent):
171 175 """
172 176 An instance of this class is emitted as an :term:`event` after a pull
173 177 request comment is edited.
174 178 """
175 name = 'pullrequest-comment-edit'
176 display_name = lazy_ugettext('pullrequest comment edited')
177 description = lazy_ugettext('Event triggered after a comment was edited on a code '
178 'in the pull request')
179
180 name = "pullrequest-comment-edit"
181 display_name = lazy_ugettext("pullrequest comment edited")
182 description = lazy_ugettext("Event triggered after a comment was edited on a code in the pull request")
179 183
180 184 def __init__(self, pullrequest, comment):
181 185 super().__init__(pullrequest)
182 186 self.comment = comment
183 187
184 188 def as_dict(self):
185 189 from rhodecode.model.comment import CommentsModel
190
186 191 data = super().as_dict()
187 192
188 193 status = None
189 194 if self.comment.status_change:
190 195 status = self.comment.review_status
191 196
192 data.update({
193 'comment': {
194 'status': status,
195 'text': self.comment.text,
196 'type': self.comment.comment_type,
197 'file': self.comment.f_path,
198 'line': self.comment.line_no,
199 'version': self.comment.last_version,
200 'url': CommentsModel().get_url(
201 self.comment, request=self.request),
202 'permalink_url': CommentsModel().get_url(
203 self.comment, request=self.request, permalink=True),
197 data.update(
198 {
199 "comment": {
200 "status": status,
201 "text": self.comment.text,
202 "type": self.comment.comment_type,
203 "file": self.comment.f_path,
204 "line": self.comment.line_no,
205 "version": self.comment.last_version,
206 "url": CommentsModel().get_url(self.comment, request=self.request),
207 "permalink_url": CommentsModel().get_url(self.comment, request=self.request, permalink=True),
208 },
209 "context": self.context
204 210 }
205 })
211 )
206 212 return data
@@ -1,444 +1,427 b''
1 1 # Copyright (C) 2016-2024 RhodeCode GmbH
2 2 #
3 3 # This program is free software: you can redistribute it and/or modify
4 4 # it under the terms of the GNU Affero General Public License, version 3
5 5 # (only), as published by the Free Software Foundation.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU Affero General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 #
15 15 # This program is dual-licensed. If you wish to learn more about the
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 19 import collections
20 20 import logging
21 21 import datetime
22 22
23 23 from rhodecode.translation import lazy_ugettext
24 24 from rhodecode.model.db import User, Repository
25 25 from rhodecode.events.base import RhodeCodeIntegrationEvent
26 26 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
27 27
28 28 log = logging.getLogger(__name__)
29 29
30 30
31 31 def _commits_as_dict(event, commit_ids, repos):
32 32 """
33 33 Helper function to serialize commit_ids
34 34
35 35 :param event: class calling this method
36 36 :param commit_ids: commits to get
37 37 :param repos: a list of repos to check
38 38 """
39 39 from rhodecode.lib.utils2 import extract_mentioned_users
40 from rhodecode.lib.helpers import (
41 urlify_commit_message, process_patterns, chop_at_smart)
40 from rhodecode.lib.helpers import urlify_commit_message, process_patterns, chop_at_smart
42 41 from rhodecode.model.repo import RepoModel
43 42
44 43 if not repos:
45 raise Exception('no repo defined')
44 raise Exception("no repo defined")
46 45
47 46 if not isinstance(repos, (tuple, list)):
48 47 repos = [repos]
49 48
50 49 if not commit_ids:
51 50 return []
52 51
53 52 needed_commits = list(commit_ids)
54 53
55 54 commits = []
56 55 reviewers = []
57 56 for repo in repos:
58 57 if not needed_commits:
59 58 return commits # return early if we have the commits we need
60 59
61 60 vcs_repo = repo.scm_instance(cache=False)
62 61
63 62 try:
64 63 # use copy of needed_commits since we modify it while iterating
65 64 for commit_id in list(needed_commits):
66 if commit_id.startswith('tag=>'):
65 if commit_id.startswith("tag=>"):
67 66 raw_id = commit_id[5:]
68 67 cs_data = {
69 'raw_id': commit_id, 'short_id': commit_id,
70 'branch': None,
71 'git_ref_change': 'tag_add',
72 'message': f'Added new tag {raw_id}',
73 'author': event.actor.full_contact,
74 'date': datetime.datetime.now(),
75 'refs': {
76 'branches': [],
77 'bookmarks': [],
78 'tags': []
79 }
68 "raw_id": commit_id,
69 "short_id": commit_id,
70 "branch": None,
71 "git_ref_change": "tag_add",
72 "message": f"Added new tag {raw_id}",
73 "author": event.actor.full_contact,
74 "date": datetime.datetime.now(),
75 "refs": {"branches": [], "bookmarks": [], "tags": []},
80 76 }
81 77 commits.append(cs_data)
82 78
83 elif commit_id.startswith('delete_branch=>'):
79 elif commit_id.startswith("delete_branch=>"):
84 80 raw_id = commit_id[15:]
85 81 cs_data = {
86 'raw_id': commit_id, 'short_id': commit_id,
87 'branch': None,
88 'git_ref_change': 'branch_delete',
89 'message': f'Deleted branch {raw_id}',
90 'author': event.actor.full_contact,
91 'date': datetime.datetime.now(),
92 'refs': {
93 'branches': [],
94 'bookmarks': [],
95 'tags': []
96 }
82 "raw_id": commit_id,
83 "short_id": commit_id,
84 "branch": None,
85 "git_ref_change": "branch_delete",
86 "message": f"Deleted branch {raw_id}",
87 "author": event.actor.full_contact,
88 "date": datetime.datetime.now(),
89 "refs": {"branches": [], "bookmarks": [], "tags": []},
97 90 }
98 91 commits.append(cs_data)
99 92
100 93 else:
101 94 try:
102 95 cs = vcs_repo.get_commit(commit_id)
103 96 except CommitDoesNotExistError:
104 97 continue # maybe its in next repo
105 98
106 99 cs_data = cs.__json__()
107 cs_data['refs'] = cs._get_refs()
100 cs_data["refs"] = cs._get_refs()
108 101
109 cs_data['mentions'] = extract_mentioned_users(cs_data['message'])
110 cs_data['reviewers'] = reviewers
111 cs_data['url'] = RepoModel().get_commit_url(
112 repo, cs_data['raw_id'], request=event.request)
113 cs_data['permalink_url'] = RepoModel().get_commit_url(
114 repo, cs_data['raw_id'], request=event.request,
115 permalink=True)
116 urlified_message, issues_data, errors = process_patterns(
117 cs_data['message'], repo.repo_name)
118 cs_data['issues'] = issues_data
119 cs_data['message_html'] = urlify_commit_message(
120 cs_data['message'], repo.repo_name)
121 cs_data['message_html_title'] = chop_at_smart(
122 cs_data['message'], '\n', suffix_if_chopped='...')
102 cs_data["mentions"] = extract_mentioned_users(cs_data["message"])
103 cs_data["reviewers"] = reviewers
104 cs_data["url"] = RepoModel().get_commit_url(repo, cs_data["raw_id"], request=event.request)
105 cs_data["permalink_url"] = RepoModel().get_commit_url(
106 repo, cs_data["raw_id"], request=event.request, permalink=True
107 )
108 urlified_message, issues_data, errors = process_patterns(cs_data["message"], repo.repo_name)
109 cs_data["issues"] = issues_data
110 cs_data["message_html"] = urlify_commit_message(cs_data["message"], repo.repo_name)
111 cs_data["message_html_title"] = chop_at_smart(cs_data["message"], "\n", suffix_if_chopped="...")
123 112 commits.append(cs_data)
124 113
125 114 needed_commits.remove(commit_id)
126 115
127 116 except Exception:
128 log.exception('Failed to extract commits data')
117 log.exception("Failed to extract commits data")
129 118 # we don't send any commits when crash happens, only full list
130 119 # matters we short circuit then.
131 120 return []
132 121
133 122 # we failed to remove all needed_commits from all repositories
134 123 if needed_commits:
135 raise ValueError(f'Unexpectedly not found {needed_commits} in all available repos {repos}')
124 raise ValueError(f"Unexpectedly not found {needed_commits} in all available repos {repos}")
136 125
137 missing_commits = set(commit_ids) - set(c['raw_id'] for c in commits)
126 missing_commits = set(commit_ids) - set(c["raw_id"] for c in commits)
138 127 if missing_commits:
139 log.error('Inconsistent repository state. '
140 'Missing commits: %s', ', '.join(missing_commits))
128 log.error("Inconsistent repository state. " "Missing commits: %s", ", ".join(missing_commits))
141 129
142 130 return commits
143 131
144 132
145 133 def _issues_as_dict(commits):
146 134 """ Helper function to serialize issues from commits """
147 135 issues = {}
148 136 for commit in commits:
149 for issue in commit['issues']:
150 issues[issue['id']] = issue
137 for issue in commit["issues"]:
138 issues[issue["id"]] = issue
151 139 return issues
152 140
153 141
154 142 class RepoEvent(RhodeCodeIntegrationEvent):
155 143 """
156 144 Base class for events acting on a repository.
157 145 """
158 146
159 def __init__(self, repo, actor=None):
147 def __init__(self, repo, actor=None, context=None):
160 148 """
161 149 :param repo: a :class:`Repository` instance
162 150 """
163 super().__init__(actor=actor)
151 super().__init__(actor=actor, context=context)
164 152 self.repo = repo
153 self.context = self._context
165 154
166 155 def as_dict(self):
167 156 from rhodecode.model.repo import RepoModel
157
168 158 data = super().as_dict()
169 159
170 160 extra_fields = collections.OrderedDict()
171 161 for field in self.repo.extra_fields:
172 162 extra_fields[field.field_key] = field.field_value
173 163
174 data.update({
175 'repo': {
176 'repo_id': self.repo.repo_id,
177 'repo_name': self.repo.repo_name,
178 'repo_type': self.repo.repo_type,
179 'url': RepoModel().get_url(
180 self.repo, request=self.request),
181 'permalink_url': RepoModel().get_url(
182 self.repo, request=self.request, permalink=True),
183 'extra_fields': extra_fields
164 data.update(
165 {
166 "repo": {
167 "repo_id": self.repo.repo_id,
168 "repo_name": self.repo.repo_name,
169 "repo_type": self.repo.repo_type,
170 "url": RepoModel().get_url(self.repo, request=self.request),
171 "permalink_url": RepoModel().get_url(self.repo, request=self.request, permalink=True),
172 "extra_fields": extra_fields,
173 },
174 "context": self.context,
184 175 }
185 })
176 )
186 177 return data
187 178
188 179
189 180 class RepoCommitCommentEvent(RepoEvent):
190 181 """
191 182 An instance of this class is emitted as an :term:`event` after a comment is made
192 183 on repository commit.
193 184 """
194 185
195 name = 'repo-commit-comment'
196 display_name = lazy_ugettext('repository commit comment')
197 description = lazy_ugettext('Event triggered after a comment was made '
198 'on commit inside a repository')
186 name = "repo-commit-comment"
187 display_name = lazy_ugettext("repository commit comment")
188 description = lazy_ugettext("Event triggered after a comment was made on commit inside a repository")
199 189
200 def __init__(self, repo, commit, comment):
201 super().__init__(repo)
190 def __init__(self, repo, commit, comment, context=None):
191 super().__init__(repo, context=context)
202 192 self.commit = commit
203 193 self.comment = comment
204 194
205 195 def as_dict(self):
206 196 data = super().as_dict()
207 data['commit'] = {
208 'commit_id': self.commit.raw_id,
209 'commit_message': self.commit.message,
210 'commit_branch': self.commit.branch,
197 data["commit"] = {
198 "commit_id": self.commit.raw_id,
199 "commit_message": self.commit.message,
200 "commit_branch": self.commit.branch,
211 201 }
212 202
213 data['comment'] = {
214 'comment_id': self.comment.comment_id,
215 'comment_text': self.comment.text,
216 'comment_type': self.comment.comment_type,
217 'comment_f_path': self.comment.f_path,
218 'comment_line_no': self.comment.line_no,
219 'comment_version': self.comment.last_version,
203 data["comment"] = {
204 "comment_id": self.comment.comment_id,
205 "comment_text": self.comment.text,
206 "comment_type": self.comment.comment_type,
207 "comment_f_path": self.comment.f_path,
208 "comment_line_no": self.comment.line_no,
209 "comment_version": self.comment.last_version,
220 210 }
211 data["contex"] = self.context
221 212 return data
222 213
223 214
224 215 class RepoCommitCommentEditEvent(RepoEvent):
225 216 """
226 217 An instance of this class is emitted as an :term:`event` after a comment is edited
227 218 on repository commit.
228 219 """
229 220
230 name = 'repo-commit-edit-comment'
231 display_name = lazy_ugettext('repository commit edit comment')
232 description = lazy_ugettext('Event triggered after a comment was edited '
233 'on commit inside a repository')
221 name = "repo-commit-edit-comment"
222 display_name = lazy_ugettext("repository commit edit comment")
223 description = lazy_ugettext("Event triggered after a comment was edited on commit inside a repository")
234 224
235 def __init__(self, repo, commit, comment):
236 super().__init__(repo)
225 def __init__(self, repo, commit, comment, context=None):
226 super().__init__(repo, context=context)
237 227 self.commit = commit
238 228 self.comment = comment
239 229
240 230 def as_dict(self):
241 231 data = super().as_dict()
242 data['commit'] = {
243 'commit_id': self.commit.raw_id,
244 'commit_message': self.commit.message,
245 'commit_branch': self.commit.branch,
232 data["commit"] = {
233 "commit_id": self.commit.raw_id,
234 "commit_message": self.commit.message,
235 "commit_branch": self.commit.branch,
246 236 }
247 237
248 data['comment'] = {
249 'comment_id': self.comment.comment_id,
250 'comment_text': self.comment.text,
251 'comment_type': self.comment.comment_type,
252 'comment_f_path': self.comment.f_path,
253 'comment_line_no': self.comment.line_no,
254 'comment_version': self.comment.last_version,
238 data["comment"] = {
239 "comment_id": self.comment.comment_id,
240 "comment_text": self.comment.text,
241 "comment_type": self.comment.comment_type,
242 "comment_f_path": self.comment.f_path,
243 "comment_line_no": self.comment.line_no,
244 "comment_version": self.comment.last_version,
255 245 }
246 data["context"] = "context"
256 247 return data
257 248
258 249
259 250 class RepoPreCreateEvent(RepoEvent):
260 251 """
261 252 An instance of this class is emitted as an :term:`event` before a repo is
262 253 created.
263 254 """
264 name = 'repo-pre-create'
265 display_name = lazy_ugettext('repository pre create')
266 description = lazy_ugettext('Event triggered before repository is created')
255
256 name = "repo-pre-create"
257 display_name = lazy_ugettext("repository pre create")
258 description = lazy_ugettext("Event triggered before repository is created")
267 259
268 260
269 261 class RepoCreateEvent(RepoEvent):
270 262 """
271 263 An instance of this class is emitted as an :term:`event` whenever a repo is
272 264 created.
273 265 """
274 name = 'repo-create'
275 display_name = lazy_ugettext('repository created')
276 description = lazy_ugettext('Event triggered after repository was created')
266
267 name = "repo-create"
268 display_name = lazy_ugettext("repository created")
269 description = lazy_ugettext("Event triggered after repository was created")
277 270
278 271
279 272 class RepoPreDeleteEvent(RepoEvent):
280 273 """
281 274 An instance of this class is emitted as an :term:`event` whenever a repo is
282 275 created.
283 276 """
284 name = 'repo-pre-delete'
285 display_name = lazy_ugettext('repository pre delete')
286 description = lazy_ugettext('Event triggered before a repository is deleted')
277
278 name = "repo-pre-delete"
279 display_name = lazy_ugettext("repository pre delete")
280 description = lazy_ugettext("Event triggered before a repository is deleted")
287 281
288 282
289 283 class RepoDeleteEvent(RepoEvent):
290 284 """
291 285 An instance of this class is emitted as an :term:`event` whenever a repo is
292 286 created.
293 287 """
294 name = 'repo-delete'
295 display_name = lazy_ugettext('repository deleted')
296 description = lazy_ugettext('Event triggered after repository was deleted')
288
289 name = "repo-delete"
290 display_name = lazy_ugettext("repository deleted")
291 description = lazy_ugettext("Event triggered after repository was deleted")
297 292
298 293
299 294 class RepoVCSEvent(RepoEvent):
300 295 """
301 296 Base class for events triggered by the VCS
302 297 """
303 name = ''
304 display_name = 'generic_vcs_event'
305 298
306 def __init__(self, repo_name, extras):
299 name = ""
300 display_name = "generic_vcs_event"
301
302 def __init__(self, repo_name, extras, context=None):
307 303 self.repo = Repository.get_by_repo_name(repo_name)
308 304 if not self.repo:
309 raise Exception(f'repo by this name {repo_name} does not exist')
305 raise Exception(f"repo by this name {repo_name} does not exist")
310 306 self.extras = extras
311 super().__init__(self.repo)
307 super().__init__(self.repo, context=context)
312 308
313 309 @property
314 310 def actor(self):
315 if self.extras.get('username'):
316 return User.get_by_username(self.extras['username'])
311 if self.extras.get("username"):
312 return User.get_by_username(self.extras["username"])
317 313
318 314 @property
319 315 def actor_ip(self):
320 if self.extras.get('ip'):
321 return self.extras['ip']
316 if self.extras.get("ip"):
317 return self.extras["ip"]
322 318
323 319 @property
324 320 def server_url(self):
325 if self.extras.get('server_url'):
326 return self.extras['server_url']
321 if self.extras.get("server_url"):
322 return self.extras["server_url"]
327 323
328 324 @property
329 325 def request(self):
330 return self.extras.get('request') or self.get_request()
326 return self.extras.get("request") or self.get_request()
331 327
332 328
333 329 class RepoPrePullEvent(RepoVCSEvent):
334 330 """
335 331 An instance of this class is emitted as an :term:`event` before commits
336 332 are pulled from a repo.
337 333 """
338 name = 'repo-pre-pull'
339 display_name = lazy_ugettext('repository pre pull')
340 description = lazy_ugettext('Event triggered before repository code is pulled')
334
335 name = "repo-pre-pull"
336 display_name = lazy_ugettext("repository pre pull")
337 description = lazy_ugettext("Event triggered before repository code is pulled")
341 338
342 339
343 340 class RepoPullEvent(RepoVCSEvent):
344 341 """
345 342 An instance of this class is emitted as an :term:`event` after commits
346 343 are pulled from a repo.
347 344 """
348 name = 'repo-pull'
349 display_name = lazy_ugettext('repository pull')
350 description = lazy_ugettext('Event triggered after repository code was pulled')
345
346 name = "repo-pull"
347 display_name = lazy_ugettext("repository pull")
348 description = lazy_ugettext("Event triggered after repository code was pulled")
351 349
352 350
353 351 class RepoPrePushEvent(RepoVCSEvent):
354 352 """
355 353 An instance of this class is emitted as an :term:`event` before commits
356 354 are pushed to a repo.
357 355 """
358 name = 'repo-pre-push'
359 display_name = lazy_ugettext('repository pre push')
360 description = lazy_ugettext('Event triggered before the code is '
361 'pushed to a repository')
356
357 name = "repo-pre-push"
358 display_name = lazy_ugettext("repository pre push")
359 description = lazy_ugettext("Event triggered before the code is pushed to a repository")
362 360
363 361
364 362 class RepoPushEvent(RepoVCSEvent):
365 363 """
366 364 An instance of this class is emitted as an :term:`event` after commits
367 365 are pushed to a repo.
368 366
369 367 :param extras: (optional) dict of data from proxied VCS actions
370 368 """
371 name = 'repo-push'
372 display_name = lazy_ugettext('repository push')
373 description = lazy_ugettext('Event triggered after the code was '
374 'pushed to a repository')
375 369
376 def __init__(self, repo_name, pushed_commit_ids, extras):
377 super().__init__(repo_name, extras)
370 name = "repo-push"
371 display_name = lazy_ugettext("repository push")
372 description = lazy_ugettext("Event triggered after the code was pushed to a repository")
373
374 def __init__(self, repo_name, pushed_commit_ids, extras, context=None):
375 super().__init__(repo_name, extras, context=context)
378 376 self.pushed_commit_ids = pushed_commit_ids
379 377 self.new_refs = extras.new_refs
380 378
381 379 def as_dict(self):
382 380 data = super().as_dict()
383 381
384 382 def branch_url(branch_name):
385 return '{}/changelog?branch={}'.format(
386 data['repo']['url'], branch_name)
383 return "{}/changelog?branch={}".format(data["repo"]["url"], branch_name)
387 384
388 385 def tag_url(tag_name):
389 return '{}/files/{}/'.format(
390 data['repo']['url'], tag_name)
386 return "{}/files/{}/".format(data["repo"]["url"], tag_name)
391 387
392 commits = _commits_as_dict(
393 self, commit_ids=self.pushed_commit_ids, repos=[self.repo])
388 commits = _commits_as_dict(self, commit_ids=self.pushed_commit_ids, repos=[self.repo])
394 389
395 390 last_branch = None
396 391 for commit in reversed(commits):
397 commit['branch'] = commit['branch'] or last_branch
398 last_branch = commit['branch']
392 commit["branch"] = commit["branch"] or last_branch
393 last_branch = commit["branch"]
399 394 issues = _issues_as_dict(commits)
400 395
401 396 branches = set()
402 397 tags = set()
403 398 for commit in commits:
404 if commit['refs']['tags']:
405 for tag in commit['refs']['tags']:
399 if commit["refs"]["tags"]:
400 for tag in commit["refs"]["tags"]:
406 401 tags.add(tag)
407 if commit['branch']:
408 branches.add(commit['branch'])
402 if commit["branch"]:
403 branches.add(commit["branch"])
409 404
410 405 # maybe we have branches in new_refs ?
411 406 try:
412 branches = branches.union(set(self.new_refs['branches']))
407 branches = branches.union(set(self.new_refs["branches"]))
413 408 except Exception:
414 409 pass
415 410
416 branches = [
417 {
418 'name': branch,
419 'url': branch_url(branch)
420 }
421 for branch in branches
422 ]
411 branches = [{"name": branch, "url": branch_url(branch)} for branch in branches]
423 412
424 413 # maybe we have branches in new_refs ?
425 414 try:
426 tags = tags.union(set(self.new_refs['tags']))
415 tags = tags.union(set(self.new_refs["tags"]))
427 416 except Exception:
428 417 pass
429 418
430 tags = [
431 {
432 'name': tag,
433 'url': tag_url(tag)
434 }
435 for tag in tags
436 ]
419 tags = [{"name": tag, "url": tag_url(tag)} for tag in tags]
437 420
438 data['push'] = {
439 'commits': commits,
440 'issues': issues,
441 'branches': branches,
442 'tags': tags,
421 data["push"] = {
422 "commits": commits,
423 "issues": issues,
424 "branches": branches,
425 "tags": tags,
443 426 }
444 427 return data
@@ -1,83 +1,90 b''
1 1 # Copyright (C) 2016-2024 RhodeCode GmbH
2 2 #
3 3 # This program is free software: you can redistribute it and/or modify
4 4 # it under the terms of the GNU Affero General Public License, version 3
5 5 # (only), as published by the Free Software Foundation.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU Affero General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 #
15 15 # This program is dual-licensed. If you wish to learn more about the
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 19 import logging
20 20
21 21 from rhodecode.translation import lazy_ugettext
22 22 from rhodecode.events.base import RhodeCodeIntegrationEvent
23 23
24 24
25 25 log = logging.getLogger(__name__)
26 26
27 27
28 28 class RepoGroupEvent(RhodeCodeIntegrationEvent):
29 29 """
30 30 Base class for events acting on a repository group.
31 31
32 :param repo: a :class:`RepositoryGroup` instance
32 :param repo_group: a :class:`RepositoryGroup` instance
33 33 """
34 34
35 def __init__(self, repo_group):
36 super().__init__()
35 def __init__(self, repo_group, context=None):
36 super().__init__(context=context)
37 37 self.repo_group = repo_group
38 self.context = self._context
38 39
39 40 def as_dict(self):
40 41 data = super().as_dict()
41 data.update({
42 'repo_group': {
43 'group_id': self.repo_group.group_id,
44 'group_name': self.repo_group.group_name,
45 'group_parent_id': self.repo_group.group_parent_id,
46 'group_description': self.repo_group.group_description,
47 'user_id': self.repo_group.user_id,
48 'created_by': self.repo_group.user.username,
49 'created_on': self.repo_group.created_on,
50 'enable_locking': self.repo_group.enable_locking,
42 data.update(
43 {
44 "repo_group": {
45 "group_id": self.repo_group.group_id,
46 "group_name": self.repo_group.group_name,
47 "group_parent_id": self.repo_group.group_parent_id,
48 "group_description": self.repo_group.group_description,
49 "user_id": self.repo_group.user_id,
50 "created_by": self.repo_group.user.username,
51 "created_on": self.repo_group.created_on,
52 "enable_locking": self.repo_group.enable_locking,
53 },
54 "context": self.context
51 55 }
52 })
56 )
53 57 return data
54 58
55 59
56 60 class RepoGroupCreateEvent(RepoGroupEvent):
57 61 """
58 62 An instance of this class is emitted as an :term:`event` whenever a
59 63 repository group is created.
60 64 """
61 name = 'repo-group-create'
62 display_name = lazy_ugettext('repository group created')
63 description = lazy_ugettext('Event triggered after a repository group was created')
65
66 name = "repo-group-create"
67 display_name = lazy_ugettext("repository group created")
68 description = lazy_ugettext("Event triggered after a repository group was created")
64 69
65 70
66 71 class RepoGroupDeleteEvent(RepoGroupEvent):
67 72 """
68 73 An instance of this class is emitted as an :term:`event` whenever a
69 74 repository group is deleted.
70 75 """
71 name = 'repo-group-delete'
72 display_name = lazy_ugettext('repository group deleted')
73 description = lazy_ugettext('Event triggered after a repository group was deleted')
76
77 name = "repo-group-delete"
78 display_name = lazy_ugettext("repository group deleted")
79 description = lazy_ugettext("Event triggered after a repository group was deleted")
74 80
75 81
76 82 class RepoGroupUpdateEvent(RepoGroupEvent):
77 83 """
78 84 An instance of this class is emitted as an :term:`event` whenever a
79 85 repository group is updated.
80 86 """
81 name = 'repo-group-update'
82 display_name = lazy_ugettext('repository group update')
83 description = lazy_ugettext('Event triggered after a repository group was updated')
87
88 name = "repo-group-update"
89 display_name = lazy_ugettext("repository group update")
90 description = lazy_ugettext("Event triggered after a repository group was updated")
@@ -1,104 +1,109 b''
1 1 # Copyright (C) 2016-2024 RhodeCode GmbH
2 2 #
3 3 # This program is free software: you can redistribute it and/or modify
4 4 # it under the terms of the GNU Affero General Public License, version 3
5 5 # (only), as published by the Free Software Foundation.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU Affero General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 #
15 15 # This program is dual-licensed. If you wish to learn more about the
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 import logging
19 19
20 20 from zope.interface import implementer
21 21
22 22 from rhodecode.translation import lazy_ugettext
23 23 from rhodecode.events.base import RhodecodeEvent, RhodeCodeIntegrationEvent
24 from rhodecode.events.interfaces import (
25 IUserRegistered, IUserPreCreate, IUserPreUpdate)
24 from rhodecode.events.interfaces import IUserRegistered, IUserPreCreate, IUserPreUpdate
26 25
27 26 log = logging.getLogger(__name__)
28 27
29 28
30 29 @implementer(IUserRegistered)
31 30 class UserRegistered(RhodeCodeIntegrationEvent):
32 31 """
33 32 An instance of this class is emitted as an :term:`event` whenever a user
34 33 account is registered.
35 34 """
36 name = 'user-register'
37 display_name = lazy_ugettext('user registered')
35
36 name = "user-register"
37 display_name = lazy_ugettext("user registered")
38 38
39 39 def __init__(self, user, session):
40 40 super().__init__()
41 41 self.user = user
42 42 self.session = session
43 43
44 44
45 45 @implementer(IUserPreCreate)
46 46 class UserPreCreate(RhodeCodeIntegrationEvent):
47 47 """
48 48 An instance of this class is emitted as an :term:`event` before a new user
49 49 object is created.
50 50 """
51 name = 'user-pre-create'
52 display_name = lazy_ugettext('user pre create')
51
52 name = "user-pre-create"
53 display_name = lazy_ugettext("user pre create")
53 54
54 55 def __init__(self, user_data):
55 56 super().__init__()
56 57 self.user_data = user_data
57 58
58 59
59 60 @implementer(IUserPreCreate)
60 61 class UserPostCreate(RhodeCodeIntegrationEvent):
61 62 """
62 63 An instance of this class is emitted as an :term:`event` after a new user
63 64 object is created.
64 65 """
65 name = 'user-post-create'
66 display_name = lazy_ugettext('user post create')
66
67 name = "user-post-create"
68 display_name = lazy_ugettext("user post create")
67 69
68 70 def __init__(self, user_data):
69 71 super().__init__()
70 72 self.user_data = user_data
71 73
72 74
73 75 @implementer(IUserPreUpdate)
74 76 class UserPreUpdate(RhodeCodeIntegrationEvent):
75 77 """
76 78 An instance of this class is emitted as an :term:`event` before a user
77 79 object is updated.
78 80 """
79 name = 'user-pre-update'
80 display_name = lazy_ugettext('user pre update')
81
82 name = "user-pre-update"
83 display_name = lazy_ugettext("user pre update")
81 84
82 85 def __init__(self, user, user_data):
83 86 super().__init__()
84 87 self.user = user
85 88 self.user_data = user_data
86 89
87 90
88 91 class UserPermissionsChange(RhodecodeEvent):
89 92 """
90 This event should be triggered on an event that permissions of user might changed.
91 Currently this should be triggered on:
93 This event should be triggered on an event that permissions of user might be changed.
94 Currently, this should be triggered on:
92 95
93 96 - user added/removed from user group
94 97 - repo permissions changed
95 98 - repo group permissions changed
96 99 - user group permissions changed
97 100
98 101 """
99 name = 'user-permissions-change'
100 display_name = lazy_ugettext('user permissions change')
102
103 name = "user-permissions-change"
104 display_name = lazy_ugettext("user permissions change")
101 105
102 def __init__(self, user_ids):
103 super().__init__()
106 def __init__(self, user_ids, context=None):
107 super().__init__(context=context)
104 108 self.user_ids = user_ids
109 self.context = self._context
General Comments 0
You need to be logged in to leave comments. Login now