Show More
@@ -1,150 +1,149 b'' | |||
|
1 |
======================== |
|
|
2 |
|
|
|
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: |
|
|
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