##// END OF EJS Templates
docs update
marcink -
r1839:9da24750 beta
parent child Browse files
Show More
@@ -1,150 +1,149 b''
1 =================================================
2 Welcome to RhodeCode (RhodiumCode) documentation!
3 =================================================
1 ========================
2 RhodeCode documentation!
3 ========================
4 4
5 5 ``RhodeCode`` is a fast and powerful management tool for Mercurial_ and GIT_
6 6 with a built in push/pull server and full text search.
7 7 It works on http/https and has a built in permission/authentication system with
8 8 the ability to authenticate via LDAP or ActiveDirectory. RhodeCode also supports
9 9 simple API so it's easy integrable with existing external systems.
10 10
11 11 RhodeCode is similar in some respects to github or bitbucket_,
12 12 however RhodeCode can be run as standalone hosted application on your own server.
13 13 It is open source and donation ware and focuses more on providing a customized,
14 14 self administered interface for Mercurial and GIT repositories.
15 15 RhodeCode is powered by a vcs_ library that Lukasz Balcerzak and I created to
16 16 handle multiple different version control systems.
17 17
18 18 RhodeCode uses `Semantic Versioning <http://semver.org/>`_
19 19
20 20 RhodeCode demo
21 21 --------------
22 22
23 23 http://demo.rhodecode.org
24 24
25 25 The default access is anonymous but you can login to an administrative account
26 26 using the following credentials:
27 27
28 28 - username: demo
29 29 - password: demo12
30 30
31 31 Source code
32 32 -----------
33 33
34 34 The latest sources can be obtained from official RhodeCode instance
35 35 https://secure.rhodecode.org
36 36
37 37
38 38 MIRRORS:
39 39
40 40 Issue tracker and sources at bitbucket_
41 41
42 42 http://bitbucket.org/marcinkuzminski/rhodecode
43 43
44 44 Sources at github_
45 45
46 46 https://github.com/marcinkuzminski/rhodecode
47 47
48 48 Installation
49 49 ------------
50 50
51 51 Please visit http://packages.python.org/RhodeCode/installation.html
52 52
53 53
54 54 RhodeCode Features
55 55 ------------------
56 56
57 57 - Has its own middleware to handle mercurial_ protocol requests.
58 58 Each request can be logged and authenticated.
59 59 - Runs on threads unlike hgweb. You can make multiple pulls/pushes simultaneous.
60 60 Supports http/https and LDAP
61 61 - Full permissions (private/read/write/admin) and authentication per project.
62 62 One account for web interface and mercurial_ push/pull/clone operations.
63 63 - Have built in users groups for easier permission management
64 64 - Repository groups let you group repos and manage them easier.
65 65 - Users can fork other users repo. RhodeCode have also compare view to see
66 66 combined changeset for all changeset made within single push.
67 67 - Build in commit-api let's you add, edit and commit files right from RhodeCode
68 68 interface using simple editor or upload form for binaries.
69 69 - Mako templates let's you customize the look and feel of the application.
70 70 - Beautiful diffs, annotations and source code browsing all colored by pygments.
71 71 Raw diffs are made in git-diff format, including git_ binary-patches
72 72 - Mercurial_ branch graph and yui-flot powered graphs with zooming and statistics
73 73 - Admin interface with user/permission management. Admin activity journal, logs
74 74 pulls, pushes, forks, registrations and other actions made by all users.
75 75 - Server side forks. It is possible to fork a project and modify it freely
76 76 without breaking the main repository. You can even write Your own hooks
77 77 and install them
78 78 - code review with notification system, inline commenting, all parsed using
79 79 rst syntax
80 80 - rst and markdown README support for repositories
81 81 - Full text search powered by Whoosh on the source files, and file names.
82 82 Build in indexing daemons, with optional incremental index build
83 83 (no external search servers required all in one application)
84 84 - Setup project descriptions and info inside built in db for easy, non
85 85 file-system operations
86 86 - Intelligent cache with invalidation after push or project change, provides
87 87 high performance and always up to date data.
88 88 - Rss / atom feeds, gravatar support, download sources as zip/tar/gz
89 89 - Async tasks for speed and performance using celery_ (works without them too)
90 90 - Backup scripts can do backup of whole app and send it over scp to desired
91 91 location
92 92 - Based on pylons / sqlalchemy / sqlite / whoosh / vcs
93 93
94 94
95 95 .. include:: ./docs/screenshots.rst
96 96
97 97
98 98 Incoming / Plans
99 99 ----------------
100 100
101 101 - Finer granular permissions per branch, repo group or subrepo
102 102 - pull requests and web based merges
103 103 - per line file history
104 104 - SSH based authentication with server side key management
105 - Redmine and other bugtrackers integration
106 105 - Commit based built in wiki system
107 106 - More statistics and graph (global annotation + some more statistics)
108 107 - Other advancements as development continues (or you can of course make
109 108 additions and or requests)
110 109
111 110 License
112 111 -------
113 112
114 113 ``RhodeCode`` is released under the GPLv3 license.
115 114
116 115
117 116 Mailing group Q&A
118 117 -----------------
119 118
120 119 Join the `Google group <http://groups.google.com/group/rhodecode>`_
121 120
122 121 Open an issue at `issue tracker <http://bitbucket.org/marcinkuzminski/rhodecode/issues>`_
123 122
124 123 Join #rhodecode on FreeNode (irc.freenode.net)
125 124 or use http://webchat.freenode.net/?channels=rhodecode for web access to irc.
126 125
127 126 Online documentation
128 127 --------------------
129 128
130 129 Online documentation for the current version of RhodeCode is available at
131 130 http://packages.python.org/RhodeCode/.
132 131 You may also build the documentation for yourself - go into ``docs/`` and run::
133 132
134 133 make html
135 134
136 135 (You need to have sphinx_ installed to build the documentation. If you don't
137 136 have sphinx_ installed you can install it via the command:
138 137 ``easy_install sphinx``)
139 138
140 139 .. _virtualenv: http://pypi.python.org/pypi/virtualenv
141 140 .. _python: http://www.python.org/
142 141 .. _sphinx: http://sphinx.pocoo.org/
143 142 .. _mercurial: http://mercurial.selenic.com/
144 143 .. _bitbucket: http://bitbucket.org/
145 144 .. _github: http://github.com/
146 145 .. _subversion: http://subversion.tigris.org/
147 146 .. _git: http://git-scm.com/
148 147 .. _celery: http://celeryproject.org/
149 148 .. _Sphinx: http://sphinx.pocoo.org/
150 149 .. _vcs: http://pypi.python.org/pypi/vcs No newline at end of file
@@ -1,421 +1,426 b''
1 1 .. _api:
2 2
3 3
4 4 API
5 5 ===
6 6
7 7
8 8 Starting from RhodeCode version 1.2 a simple API was implemented.
9 9 There's a single schema for calling all api methods. API is implemented
10 10 with JSON protocol both ways. An url to send API request in RhodeCode is
11 11 <your_server>/_admin/api
12 12
13 API ACCESS FOR WEB VIEWS
14 ++++++++++++++++++++++++
13 15
14 16 API access can also be turned on for each view decorated with `@LoginRequired`
15 17 decorator. To enable API access simple change standard login decorator into
16 18 `@LoginRequired(api_access=True)`. After such a change view can be accessed
17 19 by adding a GET parameter to url `?api_key=<api_key>`. By default it's only
18 20 enabled on RSS/ATOM feed views.
19 21
20 22
23 API ACCESS
24 ++++++++++
25
21 26 All clients are required to send JSON-RPC spec JSON data::
22 27
23 28 {
24 29 "id:<id>,
25 30 "api_key":"<api_key>",
26 31 "method":"<method_name>",
27 32 "args":{"<arg_key>":"<arg_val>"}
28 33 }
29 34
30 35 Example call for autopulling remotes repos using curl::
31 36 curl https://server.com/_admin/api -X POST -H 'content-type:text/plain' --data-binary '{"id":1,"api_key":"xe7cdb2v278e4evbdf5vs04v832v0efvcbcve4a3","method":"pull","args":{"repo":"CPython"}}'
32 37
33 38 Simply provide
34 39 - *id* A value of any type, which is used to match the response with the request that it is replying to.
35 40 - *api_key* for access and permission validation.
36 41 - *method* is name of method to call
37 42 - *args* is an key:value list of arguments to pass to method
38 43
39 44 .. note::
40 45
41 46 api_key can be found in your user account page
42 47
43 48
44 49 RhodeCode API will return always a JSON-RPC response::
45 50
46 51 {
47 52 "id":<id>,
48 53 "result": "<result>",
49 54 "error": null
50 55 }
51 56
52 57 All responses from API will be `HTTP/1.0 200 OK`, if there's an error while
53 58 calling api *error* key from response will contain failure description
54 59 and result will be null.
55 60
56 61 API METHODS
57 62 +++++++++++
58 63
59 64
60 65 pull
61 66 ----
62 67
63 68 Pulls given repo from remote location. Can be used to automatically keep
64 69 remote repos up to date. This command can be executed only using api_key
65 70 belonging to user with admin rights
66 71
67 72 INPUT::
68 73
69 74 api_key : "<api_key>"
70 75 method : "pull"
71 76 args : {
72 77 "repo" : "<repo_name>"
73 78 }
74 79
75 80 OUTPUT::
76 81
77 82 result : "Pulled from <repo_name>"
78 83 error : null
79 84
80 85
81 86 get_users
82 87 ---------
83 88
84 89 Lists all existing users. This command can be executed only using api_key
85 90 belonging to user with admin rights.
86 91
87 92 INPUT::
88 93
89 94 api_key : "<api_key>"
90 95 method : "get_users"
91 96 args : { }
92 97
93 98 OUTPUT::
94 99
95 100 result: [
96 101 {
97 102 "id" : "<id>",
98 103 "username" : "<username>",
99 104 "firstname": "<firstname>",
100 105 "lastname" : "<lastname>",
101 106 "email" : "<email>",
102 107 "active" : "<bool>",
103 108 "admin" :  "<bool>",
104 109 "ldap" : "<ldap_dn>"
105 110 },
106 111
107 112 ]
108 113 error: null
109 114
110 115 create_user
111 116 -----------
112 117
113 118 Creates new user in RhodeCode. This command can be executed only using api_key
114 119 belonging to user with admin rights.
115 120
116 121 INPUT::
117 122
118 123 api_key : "<api_key>"
119 124 method : "create_user"
120 125 args : {
121 126 "username" : "<username>",
122 127 "password" : "<password>",
123 128 "firstname" : "<firstname>",
124 129 "lastname" : "<lastname>",
125 130 "email" : "<useremail>"
126 131 "active" : "<bool> = True",
127 132 "admin" : "<bool> = False",
128 133 "ldap_dn" : "<ldap_dn> = None"
129 134 }
130 135
131 136 OUTPUT::
132 137
133 138 result: {
134 139 "msg" : "created new user <username>"
135 140 }
136 141 error: null
137 142
138 143 get_users_groups
139 144 ----------------
140 145
141 146 Lists all existing users groups. This command can be executed only using api_key
142 147 belonging to user with admin rights.
143 148
144 149 INPUT::
145 150
146 151 api_key : "<api_key>"
147 152 method : "get_users_groups"
148 153 args : { }
149 154
150 155 OUTPUT::
151 156
152 157 result : [
153 158 {
154 159 "id" : "<id>",
155 160 "name" : "<name>",
156 161 "active": "<bool>",
157 162 "members" : [
158 163 {
159 164 "id" : "<userid>",
160 165 "username" : "<username>",
161 166 "firstname": "<firstname>",
162 167 "lastname" : "<lastname>",
163 168 "email" : "<email>",
164 169 "active" : "<bool>",
165 170 "admin" :  "<bool>",
166 171 "ldap" : "<ldap_dn>"
167 172 },
168 173
169 174 ]
170 175 }
171 176 ]
172 177 error : null
173 178
174 179 get_users_group
175 180 ---------------
176 181
177 182 Gets an existing users group. This command can be executed only using api_key
178 183 belonging to user with admin rights.
179 184
180 185 INPUT::
181 186
182 187 api_key : "<api_key>"
183 188 method : "get_users_group"
184 189 args : {
185 190 "group_name" : "<name>"
186 191 }
187 192
188 193 OUTPUT::
189 194
190 195 result : None if group not exist
191 196 {
192 197 "id" : "<id>",
193 198 "name" : "<name>",
194 199 "active": "<bool>",
195 200 "members" : [
196 201 { "id" : "<userid>",
197 202 "username" : "<username>",
198 203 "firstname": "<firstname>",
199 204 "lastname" : "<lastname>",
200 205 "email" : "<email>",
201 206 "active" : "<bool>",
202 207 "admin" :  "<bool>",
203 208 "ldap" : "<ldap_dn>"
204 209 },
205 210
206 211 ]
207 212 }
208 213 error : null
209 214
210 215 create_users_group
211 216 ------------------
212 217
213 218 Creates new users group. This command can be executed only using api_key
214 219 belonging to user with admin rights
215 220
216 221 INPUT::
217 222
218 223 api_key : "<api_key>"
219 224 method : "create_users_group"
220 225 args: {
221 226 "name": "<name>",
222 227 "active":"<bool> = True"
223 228 }
224 229
225 230 OUTPUT::
226 231
227 232 result: {
228 233 "id": "<newusersgroupid>",
229 234 "msg": "created new users group <name>"
230 235 }
231 236 error: null
232 237
233 238 add_user_to_users_group
234 239 -----------------------
235 240
236 241 Adds a user to a users group. This command can be executed only using api_key
237 242 belonging to user with admin rights
238 243
239 244 INPUT::
240 245
241 246 api_key : "<api_key>"
242 247 method : "add_user_users_group"
243 248 args: {
244 249 "group_name" : "<groupname>",
245 250 "username" : "<username>"
246 251 }
247 252
248 253 OUTPUT::
249 254
250 255 result: {
251 256 "id": "<newusersgroupmemberid>",
252 257 "msg": "created new users group member"
253 258 }
254 259 error: null
255 260
256 261 get_repos
257 262 ---------
258 263
259 264 Lists all existing repositories. This command can be executed only using api_key
260 265 belonging to user with admin rights
261 266
262 267 INPUT::
263 268
264 269 api_key : "<api_key>"
265 270 method : "get_repos"
266 271 args: { }
267 272
268 273 OUTPUT::
269 274
270 275 result: [
271 276 {
272 277 "id" : "<id>",
273 278 "name" : "<name>"
274 279 "type" : "<type>",
275 280 "description" : "<description>"
276 281 },
277 282
278 283 ]
279 284 error: null
280 285
281 286 get_repo
282 287 --------
283 288
284 289 Gets an existing repository. This command can be executed only using api_key
285 290 belonging to user with admin rights
286 291
287 292 INPUT::
288 293
289 294 api_key : "<api_key>"
290 295 method : "get_repo"
291 296 args: {
292 297 "name" : "<name>"
293 298 }
294 299
295 300 OUTPUT::
296 301
297 302 result: None if repository not exist
298 303 {
299 304 "id" : "<id>",
300 305 "name" : "<name>"
301 306 "type" : "<type>",
302 307 "description" : "<description>",
303 308 "members" : [
304 309 { "id" : "<userid>",
305 310 "username" : "<username>",
306 311 "firstname": "<firstname>",
307 312 "lastname" : "<lastname>",
308 313 "email" : "<email>",
309 314 "active" : "<bool>",
310 315 "admin" :  "<bool>",
311 316 "ldap" : "<ldap_dn>",
312 317 "permission" : "repository.(read|write|admin)"
313 318 },
314 319
315 320 {
316 321 "id" : "<usersgroupid>",
317 322 "name" : "<usersgroupname>",
318 323 "active": "<bool>",
319 324 "permission" : "repository.(read|write|admin)"
320 325 },
321 326
322 327 ]
323 328 }
324 329 error: null
325 330
326 331 get_repo_nodes
327 332 --------------
328 333
329 334 returns a list of nodes and it's children in a flat list for a given path
330 335 at given revision. It's possible to specify ret_type to show only files or
331 336 dirs. This command can be executed only using api_key belonging to user
332 337 with admin rights
333 338
334 339 INPUT::
335 340
336 341 api_key : "<api_key>"
337 342 method : "get_repo_nodes"
338 343 args: {
339 344 "repo_name" : "<name>",
340 345 "revision" : "<revision>",
341 346 "root_path" : "<root_path>",
342 347 "ret_type" : "<ret_type>" = 'all'
343 348 }
344 349
345 350 OUTPUT::
346 351
347 352 result: [
348 353 {
349 354 "name" : "<name>"
350 355 "type" : "<type>",
351 356 },
352 357
353 358 ]
354 359 error: null
355 360
356 361
357 362
358 363 create_repo
359 364 -----------
360 365
361 366 Creates a repository. This command can be executed only using api_key
362 367 belonging to user with admin rights.
363 368 If repository name contains "/", all needed repository groups will be created.
364 369 For example "foo/bar/baz" will create groups "foo", "bar" (with "foo" as parent),
365 370 and create "baz" repository with "bar" as group.
366 371
367 372 INPUT::
368 373
369 374 api_key : "<api_key>"
370 375 method : "create_repo"
371 376 args: {
372 377 "name" : "<name>",
373 378 "owner_name" : "<ownername>",
374 379 "description" : "<description> = ''",
375 380 "repo_type" : "<type> = 'hg'",
376 381 "private" : "<bool> = False"
377 382 }
378 383
379 384 OUTPUT::
380 385
381 386 result: None
382 387 error: null
383 388
384 389 add_user_to_repo
385 390 ----------------
386 391
387 392 Add a user to a repository. This command can be executed only using api_key
388 393 belonging to user with admin rights.
389 394 If "perm" is None, user will be removed from the repository.
390 395
391 396 INPUT::
392 397
393 398 api_key : "<api_key>"
394 399 method : "add_user_to_repo"
395 400 args: {
396 401 "repo_name" : "<reponame>",
397 402 "username" : "<username>",
398 403 "perm" : "(None|repository.(read|write|admin))",
399 404 }
400 405
401 406 OUTPUT::
402 407
403 408 result: None
404 409 error: null
405 410
406 411 add_users_group_to_repo
407 412 -----------------------
408 413
409 414 Add a users group to a repository. This command can be executed only using
410 415 api_key belonging to user with admin rights. If "perm" is None, group will
411 416 be removed from the repository.
412 417
413 418 INPUT::
414 419
415 420 api_key : "<api_key>"
416 421 method : "add_users_group_to_repo"
417 422 args: {
418 423 "repo_name" : "<reponame>",
419 424 "group_name" : "<groupname>",
420 425 "perm" : "(None|repository.(read|write|admin))",
421 426 } No newline at end of file
@@ -1,10 +1,10 b''
1 .. _api:
1 .. _indexapi:
2 2
3 3 API Reference
4 4 =============
5 5
6 6 .. toctree::
7 7 :maxdepth: 3
8 8
9 9 models
10 10 api No newline at end of file
@@ -1,19 +1,34 b''
1 1 .. _models:
2 2
3 3 The :mod:`models` Module
4 4 ========================
5 5
6 6 .. automodule:: rhodecode.model
7 7 :members:
8 8
9 .. automodule:: rhodecode.model.comment
10 :members:
11
12 .. automodule:: rhodecode.model.notification
13 :members:
14
9 15 .. automodule:: rhodecode.model.permission
10 16 :members:
11
17
18 .. automodule:: rhodecode.model.repo_permission
19 :members:
20
12 21 .. automodule:: rhodecode.model.repo
13 22 :members:
14 23
24 .. automodule:: rhodecode.model.repos_group
25 :members:
26
15 27 .. automodule:: rhodecode.model.scm
16 28 :members:
17
29
18 30 .. automodule:: rhodecode.model.user
19 31 :members:
32
33 .. automodule:: rhodecode.model.users_group
34 :members: No newline at end of file
@@ -1,59 +1,58 b''
1 1 .. _index:
2 2
3 3 .. include:: ./../README.rst
4 4
5 Documentation
6 -------------
5 Users Guide
6 -----------
7 7
8 8 **Installation:**
9 9
10 10 .. toctree::
11 11 :maxdepth: 1
12 12
13 13 installation
14 14 setup
15 15 upgrade
16 16
17 17 **Usage**
18 18
19 19 .. toctree::
20 20 :maxdepth: 1
21 21
22 22 usage/general
23 23 usage/enable_git
24 24 usage/statistics
25 25 usage/backup
26 usage/api_key_access
27 26
28 27 **Develop**
29 28
30 29 .. toctree::
31 30 :maxdepth: 1
32 31
33 32 contributing
34 33 changelog
35 34
36 35 **API**
37 36
38 37 .. toctree::
39 :maxdepth: 2
38 :maxdepth: 1
40 39
41 40 api/index
42 41
43 42
44 43 Other topics
45 44 ------------
46 45
47 46 * :ref:`genindex`
48 47 * :ref:`search`
49 48
50 49 .. _virtualenv: http://pypi.python.org/pypi/virtualenv
51 50 .. _python: http://www.python.org/
52 51 .. _django: http://www.djangoproject.com/
53 52 .. _mercurial: http://mercurial.selenic.com/
54 53 .. _bitbucket: http://bitbucket.org/
55 54 .. _subversion: http://subversion.tigris.org/
56 55 .. _git: http://git-scm.com/
57 56 .. _celery: http://celeryproject.org/
58 57 .. _Sphinx: http://sphinx.pocoo.org/
59 58 .. _vcs: http://pypi.python.org/pypi/vcs No newline at end of file
@@ -1,219 +1,219 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.notification
4 ~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Model for notifications
7 7
8 8
9 9 :created_on: Nov 20, 2011
10 10 :author: marcink
11 11 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
12 12 :license: GPLv3, see COPYING for more details.
13 13 """
14 14 # This program is free software: you can redistribute it and/or modify
15 15 # it under the terms of the GNU General Public License as published by
16 16 # the Free Software Foundation, either version 3 of the License, or
17 17 # (at your option) any later version.
18 18 #
19 19 # This program is distributed in the hope that it will be useful,
20 20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 22 # GNU General Public License for more details.
23 23 #
24 24 # You should have received a copy of the GNU General Public License
25 25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 26
27 27 import os
28 28 import logging
29 29 import traceback
30 30 import datetime
31 31
32 32 from pylons.i18n.translation import _
33 33
34 34 import rhodecode
35 35 from rhodecode.lib import helpers as h
36 36 from rhodecode.model import BaseModel
37 37 from rhodecode.model.db import Notification, User, UserNotification
38 38
39 39 log = logging.getLogger(__name__)
40 40
41 41
42 42 class NotificationModel(BaseModel):
43 43
44 44 def __get_user(self, user):
45 45 if isinstance(user, basestring):
46 46 return User.get_by_username(username=user)
47 47 else:
48 48 return self._get_instance(User, user)
49 49
50 50 def __get_notification(self, notification):
51 51 if isinstance(notification, Notification):
52 52 return notification
53 53 elif isinstance(notification, int):
54 54 return Notification.get(notification)
55 55 else:
56 56 if notification:
57 57 raise Exception('notification must be int or Instance'
58 58 ' of Notification got %s' % type(notification))
59 59
60 60 def create(self, created_by, subject, body, recipients=None,
61 61 type_=Notification.TYPE_MESSAGE, with_email=True,
62 62 email_kwargs={}):
63 63 """
64 64
65 65 Creates notification of given type
66 66
67 67 :param created_by: int, str or User instance. User who created this
68 68 notification
69 69 :param subject:
70 70 :param body:
71 71 :param recipients: list of int, str or User objects, when None
72 72 is given send to all admins
73 73 :param type_: type of notification
74 74 :param with_email: send email with this notification
75 75 :param email_kwargs: additional dict to pass as args to email template
76 76 """
77 77 from rhodecode.lib.celerylib import tasks, run_task
78 78
79 79 if recipients and not getattr(recipients, '__iter__', False):
80 80 raise Exception('recipients must be a list of iterable')
81 81
82 82 created_by_obj = self.__get_user(created_by)
83 83
84 84 if recipients:
85 85 recipients_objs = []
86 86 for u in recipients:
87 87 obj = self.__get_user(u)
88 88 if obj:
89 89 recipients_objs.append(obj)
90 90 recipients_objs = set(recipients_objs)
91 91 else:
92 92 # empty recipients means to all admins
93 93 recipients_objs = User.query().filter(User.admin == True).all()
94 94
95 95 notif = Notification.create(created_by=created_by_obj, subject=subject,
96 96 body=body, recipients=recipients_objs,
97 97 type_=type_)
98 98
99 99 if with_email is False:
100 100 return notif
101 101
102 102 # send email with notification
103 103 for rec in recipients_objs:
104 104 email_subject = NotificationModel().make_description(notif, False)
105 105 type_ = type_
106 106 email_body = body
107 107 kwargs = {'subject': subject, 'body': h.rst_w_mentions(body)}
108 108 kwargs.update(email_kwargs)
109 109 email_body_html = EmailNotificationModel()\
110 110 .get_email_tmpl(type_, **kwargs)
111 111 run_task(tasks.send_email, rec.email, email_subject, email_body,
112 112 email_body_html)
113 113
114 114 return notif
115 115
116 116 def delete(self, user, notification):
117 117 # we don't want to remove actual notification just the assignment
118 118 try:
119 119 notification = self.__get_notification(notification)
120 120 user = self.__get_user(user)
121 121 if notification and user:
122 122 obj = UserNotification.query()\
123 123 .filter(UserNotification.user == user)\
124 124 .filter(UserNotification.notification
125 125 == notification)\
126 126 .one()
127 127 self.sa.delete(obj)
128 128 return True
129 129 except Exception:
130 130 log.error(traceback.format_exc())
131 131 raise
132 132
133 133 def get_for_user(self, user):
134 134 user = self.__get_user(user)
135 135 return user.notifications
136 136
137 137 def mark_all_read_for_user(self, user):
138 138 user = self.__get_user(user)
139 139 UserNotification.query()\
140 140 .filter(UserNotification.read==False)\
141 141 .update({'read': True})
142 142
143 143 def get_unread_cnt_for_user(self, user):
144 144 user = self.__get_user(user)
145 145 return UserNotification.query()\
146 146 .filter(UserNotification.read == False)\
147 147 .filter(UserNotification.user == user).count()
148 148
149 149 def get_unread_for_user(self, user):
150 150 user = self.__get_user(user)
151 151 return [x.notification for x in UserNotification.query()\
152 152 .filter(UserNotification.read == False)\
153 153 .filter(UserNotification.user == user).all()]
154 154
155 155 def get_user_notification(self, user, notification):
156 156 user = self.__get_user(user)
157 157 notification = self.__get_notification(notification)
158 158
159 159 return UserNotification.query()\
160 160 .filter(UserNotification.notification == notification)\
161 161 .filter(UserNotification.user == user).scalar()
162 162
163 163 def make_description(self, notification, show_age=True):
164 164 """
165 165 Creates a human readable description based on properties
166 166 of notification object
167 167 """
168 168
169 169 _map = {notification.TYPE_CHANGESET_COMMENT:_('commented on commit'),
170 170 notification.TYPE_MESSAGE:_('sent message'),
171 171 notification.TYPE_MENTION:_('mentioned you'),
172 172 notification.TYPE_REGISTRATION:_('registered in RhodeCode')}
173 173
174 174 DATETIME_FORMAT = "%Y-%m-%d %H:%M:%S"
175 175
176 176 tmpl = "%(user)s %(action)s %(when)s"
177 177 if show_age:
178 178 when = h.age(notification.created_on)
179 179 else:
180 180 DTF = lambda d: datetime.datetime.strftime(d, DATETIME_FORMAT)
181 181 when = DTF(notification.created_on)
182 182 data = dict(user=notification.created_by_user.username,
183 183 action=_map[notification.type_],
184 184 when=when)
185 185 return tmpl % data
186 186
187 187
188 188 class EmailNotificationModel(BaseModel):
189 189
190 190 TYPE_CHANGESET_COMMENT = Notification.TYPE_CHANGESET_COMMENT
191 191 TYPE_PASSWORD_RESET = 'passoword_link'
192 192 TYPE_REGISTRATION = Notification.TYPE_REGISTRATION
193 193 TYPE_DEFAULT = 'default'
194 194
195 195 def __init__(self):
196 196 self._template_root = rhodecode.CONFIG['pylons.paths']['templates'][0]
197 197 self._tmpl_lookup = rhodecode.CONFIG['pylons.app_globals'].mako_lookup
198 198
199 199 self.email_types = {
200 200 self.TYPE_CHANGESET_COMMENT:'email_templates/changeset_comment.html',
201 201 self.TYPE_PASSWORD_RESET:'email_templates/password_reset.html',
202 202 self.TYPE_REGISTRATION:'email_templates/registration.html',
203 203 self.TYPE_DEFAULT:'email_templates/default.html'
204 204 }
205 205
206 206 def get_email_tmpl(self, type_, **kwargs):
207 207 """
208 208 return generated template for email based on given type
209 209
210 210 :param type_:
211 211 """
212 212
213 213 base = self.email_types.get(type_, self.email_types[self.TYPE_DEFAULT])
214 214 email_template = self._tmpl_lookup.get_template(base)
215 215 # translator inject
216 216 _kwargs = {'_':_}
217 217 _kwargs.update(kwargs)
218 218 log.debug('rendering tmpl %s with kwargs %s' % (base, _kwargs))
219 219 return email_template.render(**_kwargs)
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now