You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2013/05/20 19:22:22 UTC

[1/3] git commit: [#5652] ticket:325 fixed discussion_thread_url and tests

Updated Branches:
  refs/heads/master a211a0d7f -> 0d1c69e81


[#5652]  ticket:325 fixed discussion_thread_url and tests


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/703ccaab
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/703ccaab
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/703ccaab

Branch: refs/heads/master
Commit: 703ccaab9bc4354f919129cfb85d611bad0eb056
Parents: 79e39b3
Author: Yuriy Arhipov <yu...@yandex.ru>
Authored: Thu May 9 18:50:45 2013 +0400
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Mon May 20 17:22:09 2013 +0000

----------------------------------------------------------------------
 Allura/allura/model/artifact.py                    |    5 +-
 Allura/allura/model/discuss.py                     |    5 +-
 Allura/allura/tests/functional/test_rest.py        |    6 +-
 .../tests/functional/test_rest_api_tickets.py      |    4 +-
 ForgeTracker/forgetracker/model/ticket.py          |    5 +-
 .../forgetracker/tests/functional/test_root.py     |    6 +-
 ForgeWiki/forgewiki/model/wiki.py                  |    8 ++
 ForgeWiki/forgewiki/tests/functional/test_root.py  |   10 ++-
 ForgeWiki/forgewiki/wiki_main.py                   |   51 +++++++++------
 9 files changed, 57 insertions(+), 43 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/703ccaab/Allura/allura/model/artifact.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/artifact.py b/Allura/allura/model/artifact.py
index a8f573c..5aea67f 100644
--- a/Allura/allura/model/artifact.py
+++ b/Allura/allura/model/artifact.py
@@ -19,8 +19,6 @@ import logging
 import cPickle as pickle
 from collections import defaultdict
 from datetime import datetime
-from urlparse import urljoin
-from tg import config
 
 import bson
 import pymongo
@@ -98,8 +96,7 @@ class Artifact(MappedClass):
             labels=self.labels,
             related_artifacts=[a.url() for a in self.related_artifacts()],
             discussion_thread=self.discussion_thread,
-            discussion_thread_url=urljoin(config.get('base_url', 'http://sourceforge.net/'),
-                                          '/rest%s' % self.discussion_thread.url()),
+            discussion_thread_url=h.absurl('/rest%s' % self.discussion_thread.url()),
         )
 
     def parent_security_context(self):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/703ccaab/Allura/allura/model/discuss.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/discuss.py b/Allura/allura/model/discuss.py
index e1da83c..c947c82 100644
--- a/Allura/allura/model/discuss.py
+++ b/Allura/allura/model/discuss.py
@@ -21,8 +21,6 @@ from datetime import datetime
 import pymongo
 from pymongo.errors import DuplicateKeyError
 from pylons import tmpl_context as c, app_globals as g
-from urlparse import urljoin
-from tg import config
 
 from ming import schema
 from ming.orm.base import session
@@ -168,8 +166,7 @@ class Thread(Artifact, ActivityObject):
             posts=[dict(slug=p.slug,
                         subject=p.subject,
                         attachments=[dict(bytes=attach.length,
-                                          url=urljoin(config.get('base_url', 'http://sourceforge.net/'),
-                                                      attach.url())) for attach in p.attachments])
+                                          url=h.absurl(attach.url())) for attach in p.attachments])
                    for p in self.posts])
 
     @property

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/703ccaab/Allura/allura/tests/functional/test_rest.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_rest.py b/Allura/allura/tests/functional/test_rest.py
index fcfb373..eb9dcd6 100644
--- a/Allura/allura/tests/functional/test_rest.py
+++ b/Allura/allura/tests/functional/test_rest.py
@@ -59,13 +59,13 @@ class TestRestHome(TestRestApiBase):
     def test_project_ping(self):
         r = self.api_get('/rest/p/test/wiki/Home/')
         assert r.status_int == 200
-        assert r.json['title'] == 'Home', r.json
+        assert r.json['page']['title'] == 'Home', r.json
 
     @td.with_tool('test/sub1', 'Wiki', 'wiki')
     def test_subproject_ping(self):
         r = self.api_get('/rest/p/test/sub1/wiki/Home/')
         assert r.status_int == 200
-        assert r.json['title'] == 'Home', r.json
+        assert r.json['page']['title'] == 'Home', r.json
 
     def test_project_code(self):
         r = self.api_get('/rest/p/test/')
@@ -105,7 +105,7 @@ class TestRestHome(TestRestApiBase):
                 'viewable_by-0.id':'all'})
         r = self.api_get('/rest/p/test/wiki/tést/')
         assert r.status_int == 200
-        assert r.json['title'].encode('utf-8') == 'tést', r.json
+        assert r.json['page']['title'].encode('utf-8') == 'tést', r.json
 
     @td.with_wiki
     def test_deny_access(self):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/703ccaab/Allura/allura/tests/functional/test_rest_api_tickets.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_rest_api_tickets.py b/Allura/allura/tests/functional/test_rest_api_tickets.py
index 11e149f..219f235 100644
--- a/Allura/allura/tests/functional/test_rest_api_tickets.py
+++ b/Allura/allura/tests/functional/test_rest_api_tickets.py
@@ -68,7 +68,7 @@ class TestApiTicket(TestRestApiBase):
         self.set_api_ticket()
         r = self.api_get('/rest/p/test/wiki/Home/')
         assert r.status_int == 200
-        assert r.json['title'] == 'Home', r.json
+        assert r.json['page']['title'] == 'Home', r.json
 
     def test_project_ping_expired_ticket(self):
         self.set_api_ticket(timedelta(seconds=-1))
@@ -80,4 +80,4 @@ class TestApiTicket(TestRestApiBase):
         self.set_api_ticket()
         r = self.api_get('/rest/p/test/sub1/wiki/Home/')
         assert r.status_int == 200
-        assert r.json['title'] == 'Home', r.json
+        assert r.json['page']['title'] == 'Home', r.json

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/703ccaab/ForgeTracker/forgetracker/model/ticket.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/model/ticket.py b/ForgeTracker/forgetracker/model/ticket.py
index 00851bc..7bd2386 100644
--- a/ForgeTracker/forgetracker/model/ticket.py
+++ b/ForgeTracker/forgetracker/model/ticket.py
@@ -25,8 +25,6 @@ import pymongo
 from pymongo.errors import OperationFailure
 from pylons import tmpl_context as c, app_globals as g
 from pprint import pformat
-from urlparse import urljoin
-from tg import config as tg_config
 
 from ming import schema
 from ming.utils import LazyProperty
@@ -737,8 +735,7 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
             status=self.status,
             private=self.private,
             attachments=[dict(bytes=attach.length,
-                              url=urljoin(tg_config.get('base_url', 'http://sourceforge.net/'),
-                                          attach.url())) for attach in self.attachments],
+                              url=h.absurl(attach.url())) for attach in self.attachments],
             custom_fields=self.custom_fields)
 
     @classmethod

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/703ccaab/ForgeTracker/forgetracker/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index bf498be..2bd1747 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -1715,10 +1715,10 @@ class TestFunctionalController(TrackerTestController):
         discussion_url = r.html.findAll('form')[-1]['action'][:-4]
         r = self.app.get('/rest/p/test/bugs/1/')
         r = json.loads(r.body)
-        assert_equal(r['ticket']['discussion_thread_url'],'http://localhost/rest%s' % discussion_url)
+        assert_equal(r['ticket']['discussion_thread_url'],'http://localhost:80/rest%s' % discussion_url)
         slug = r['ticket']['discussion_thread']['posts'][0]['slug']
         assert_equal(r['ticket']['discussion_thread']['posts'][0]['attachments'][0]['url'],
-                     'http://localhost%s%s/attachment/test.txt' % (discussion_url, slug))
+                     'http://localhost:80%s%s/attachment/test.txt' % (discussion_url, slug))
         assert_equal(r['ticket']['discussion_thread']['posts'][0]['attachments'][0]['bytes'], 11)
 
         file_name = 'test_root.py'
@@ -1729,7 +1729,7 @@ class TestFunctionalController(TrackerTestController):
         }, upload_files=[upload]).follow()
         r = self.app.get('/rest/p/test/bugs/1/')
         r = json.loads(r.body)
-        assert_equal(r['ticket']['attachments'][0]['url'], 'http://localhost/p/test/bugs/1/attachment/test_root.py')
+        assert_equal(r['ticket']['attachments'][0]['url'], 'http://localhost:80/p/test/bugs/1/attachment/test_root.py')
 
 
 

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/703ccaab/ForgeWiki/forgewiki/model/wiki.py
----------------------------------------------------------------------
diff --git a/ForgeWiki/forgewiki/model/wiki.py b/ForgeWiki/forgewiki/model/wiki.py
index a7ac642..6f054a1 100644
--- a/ForgeWiki/forgewiki/model/wiki.py
+++ b/ForgeWiki/forgewiki/model/wiki.py
@@ -97,6 +97,14 @@ class Page(VersionedArtifact, ActivityObject):
     def activity_name(self):
         return 'wiki page %s' % self.title
 
+    def __json__(self):
+        return dict(super(Page, self).__json__(),
+                    title=self.title,
+                    text=self.text,
+                    labels=self.labels,
+                    attachments=[dict(bytes=attach.length,
+                                      url=h.absurl(attach.url())) for attach in self.attachments])
+
     def commit(self):
         ss = VersionedArtifact.commit(self)
         session(self).flush()

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/703ccaab/ForgeWiki/forgewiki/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/ForgeWiki/forgewiki/tests/functional/test_root.py b/ForgeWiki/forgewiki/tests/functional/test_root.py
index d943530..5682d2a 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_root.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_root.py
@@ -629,6 +629,10 @@ class TestRootController(TestController):
         self.app.post('/wiki/Home/attach', upload_files=[('file_info', 'test_root.py', content)])
         r = self.app.get('/rest/p/test/wiki/Home/')
         r = json.loads(r.body)
-        assert_equal(r['attachments'][0]['url'], 'http://localhost/p/test/wiki/Home/attachment/test_root.py')
-        assert_equal(r['discussion_thread_url'], 'http://localhost/rest%s' % discussion_url)
-        assert_equal(r['discussion_thread']['_id'], discussion_url.split('/')[-2])
+        assert_equal(r['page']['attachments'][0]['url'], 'http://localhost:80/p/test/wiki/Home/attachment/test_root.py')
+        assert_equal(r['page']['discussion_thread_url'], 'http://localhost:80/rest%s' % discussion_url)
+        assert_equal(r['page']['discussion_thread']['_id'], discussion_url.split('/')[-2])
+        self.app.post('/wiki/Home/attach', upload_files=[('file_info', '__init__.py', content),])
+        r = self.app.get('/rest/p/test/wiki/Home/')
+        r = json.loads(r.body)
+        assert_equal(len(r['page']['attachments']), 2)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/703ccaab/ForgeWiki/forgewiki/wiki_main.py
----------------------------------------------------------------------
diff --git a/ForgeWiki/forgewiki/wiki_main.py b/ForgeWiki/forgewiki/wiki_main.py
index 1dc9e06..66d01b7 100644
--- a/ForgeWiki/forgewiki/wiki_main.py
+++ b/ForgeWiki/forgewiki/wiki_main.py
@@ -22,7 +22,7 @@ from urllib import unquote
 from datetime import datetime
 
 # Non-stdlib imports
-from tg import expose, validate, redirect, response, flash, config
+from tg import expose, validate, redirect, response, flash
 from tg.decorators import with_trailing_slash, without_trailing_slash
 from tg.controllers import RestController
 from pylons import tmpl_context as c, app_globals as g
@@ -30,7 +30,6 @@ from pylons import request
 from formencode import validators
 from webob import exc
 from ming.orm import session
-from urlparse import urljoin
 
 # Pyforge-specific imports
 from allura import model as M
@@ -39,7 +38,7 @@ from allura.app import Application, SitemapEntry, DefaultAdminController
 from allura.lib.search import search_app
 from allura.lib.decorators import require_post, Property
 from allura.lib.security import require_access, has_access
-from allura.controllers import AppDiscussionController, BaseController
+from allura.controllers import AppDiscussionController, BaseController, AppDiscussionRestController
 from allura.controllers import DispatchIndex
 from allura.controllers import attachments as ac
 from allura.controllers.feed import FeedArgs, FeedController
@@ -681,10 +680,16 @@ Some *emphasized* and **strong** text
 
 '''
 
-class RootRestController(RestController):
+class RootRestController(BaseController):
+
+    def __init__(self):
+        self._discuss = AppDiscussionRestController()
+
+    def _check_security(self):
+        require_access(c.app, 'read')
 
     @expose('json:')
-    def get_all(self, **kw):
+    def index(self, **kw):
         page_titles = []
         pages = WM.Page.query.find(dict(app_config_id=c.app.config._id, deleted=False))
         for page in pages:
@@ -692,21 +697,10 @@ class RootRestController(RestController):
                 page_titles.append(page.title)
         return dict(pages=page_titles)
 
-    @expose('json:')
-    def get_one(self, title, **kw):
-        page = WM.Page.query.get(app_config_id=c.app.config._id, title=h.really_unicode(title), deleted=False)
-        if page is None:
-            raise exc.HTTPNotFound, title
-        require_access(page, 'read')
-        return dict(title=page.title,
-                    text=page.text,
-                    labels=page.labels,
-                    discussion_thread=page.discussion_thread,
-                    discussion_thread_url=urljoin(config.get('base_url', 'http://sourceforge.net/'),
-                                                  '/rest%s' % page.discussion_thread.url()),
-                    attachments=[dict(bytes=attach.length,
-                                      url=urljoin(config.get('base_url', 'http://sourceforge.net/'),
-                                                  attach.url())) for attach in page.attachments])
+    @expose()
+    def _lookup(self, title, *remainder):
+        return PageRestController(title), remainder
+
 
     @h.vardec
     @expose()
@@ -727,6 +721,23 @@ class RootRestController(RestController):
             page.labels = post_data['labels'].split(',')
         page.commit()
 
+class PageRestController(BaseController):
+
+    def __init__(self, title):
+        if title is not None:
+            self.page = WM.Page.query.get(app_config_id=c.app.config._id,
+                                          title=h.really_unicode(unquote(title)),
+                                          deleted=False)
+            if self.page is None:
+                raise exc.HTTPNotFound()
+
+    def _check_security(self):
+        require_access(self.page, 'read')
+
+    @expose('json:')
+    def index(self, **kw):
+        return dict(page=self.page)
+
 
 class WikiAdminController(DefaultAdminController):
 


[3/3] git commit: [#5652] ticket:357 restore output format for wiki page api

Posted by br...@apache.org.
[#5652] ticket:357 restore output format for wiki page api


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/0d1c69e8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/0d1c69e8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/0d1c69e8

Branch: refs/heads/master
Commit: 0d1c69e81b2777911775c6e3d091bad630ec7f63
Parents: 703ccaa
Author: Yuriy Arhipov <yu...@yandex.ru>
Authored: Fri May 17 14:12:39 2013 +0400
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Mon May 20 17:22:10 2013 +0000

----------------------------------------------------------------------
 Allura/allura/tests/functional/test_rest.py        |    6 +++---
 .../tests/functional/test_rest_api_tickets.py      |    4 ++--
 ForgeWiki/forgewiki/tests/functional/test_root.py  |    8 ++++----
 ForgeWiki/forgewiki/wiki_main.py                   |    2 +-
 4 files changed, 10 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/0d1c69e8/Allura/allura/tests/functional/test_rest.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_rest.py b/Allura/allura/tests/functional/test_rest.py
index eb9dcd6..fcfb373 100644
--- a/Allura/allura/tests/functional/test_rest.py
+++ b/Allura/allura/tests/functional/test_rest.py
@@ -59,13 +59,13 @@ class TestRestHome(TestRestApiBase):
     def test_project_ping(self):
         r = self.api_get('/rest/p/test/wiki/Home/')
         assert r.status_int == 200
-        assert r.json['page']['title'] == 'Home', r.json
+        assert r.json['title'] == 'Home', r.json
 
     @td.with_tool('test/sub1', 'Wiki', 'wiki')
     def test_subproject_ping(self):
         r = self.api_get('/rest/p/test/sub1/wiki/Home/')
         assert r.status_int == 200
-        assert r.json['page']['title'] == 'Home', r.json
+        assert r.json['title'] == 'Home', r.json
 
     def test_project_code(self):
         r = self.api_get('/rest/p/test/')
@@ -105,7 +105,7 @@ class TestRestHome(TestRestApiBase):
                 'viewable_by-0.id':'all'})
         r = self.api_get('/rest/p/test/wiki/tést/')
         assert r.status_int == 200
-        assert r.json['page']['title'].encode('utf-8') == 'tést', r.json
+        assert r.json['title'].encode('utf-8') == 'tést', r.json
 
     @td.with_wiki
     def test_deny_access(self):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/0d1c69e8/Allura/allura/tests/functional/test_rest_api_tickets.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_rest_api_tickets.py b/Allura/allura/tests/functional/test_rest_api_tickets.py
index 219f235..11e149f 100644
--- a/Allura/allura/tests/functional/test_rest_api_tickets.py
+++ b/Allura/allura/tests/functional/test_rest_api_tickets.py
@@ -68,7 +68,7 @@ class TestApiTicket(TestRestApiBase):
         self.set_api_ticket()
         r = self.api_get('/rest/p/test/wiki/Home/')
         assert r.status_int == 200
-        assert r.json['page']['title'] == 'Home', r.json
+        assert r.json['title'] == 'Home', r.json
 
     def test_project_ping_expired_ticket(self):
         self.set_api_ticket(timedelta(seconds=-1))
@@ -80,4 +80,4 @@ class TestApiTicket(TestRestApiBase):
         self.set_api_ticket()
         r = self.api_get('/rest/p/test/sub1/wiki/Home/')
         assert r.status_int == 200
-        assert r.json['page']['title'] == 'Home', r.json
+        assert r.json['title'] == 'Home', r.json

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/0d1c69e8/ForgeWiki/forgewiki/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/ForgeWiki/forgewiki/tests/functional/test_root.py b/ForgeWiki/forgewiki/tests/functional/test_root.py
index 5682d2a..1baa28b 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_root.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_root.py
@@ -629,10 +629,10 @@ class TestRootController(TestController):
         self.app.post('/wiki/Home/attach', upload_files=[('file_info', 'test_root.py', content)])
         r = self.app.get('/rest/p/test/wiki/Home/')
         r = json.loads(r.body)
-        assert_equal(r['page']['attachments'][0]['url'], 'http://localhost:80/p/test/wiki/Home/attachment/test_root.py')
-        assert_equal(r['page']['discussion_thread_url'], 'http://localhost:80/rest%s' % discussion_url)
-        assert_equal(r['page']['discussion_thread']['_id'], discussion_url.split('/')[-2])
+        assert_equal(r['attachments'][0]['url'], 'http://localhost:80/p/test/wiki/Home/attachment/test_root.py')
+        assert_equal(r['discussion_thread_url'], 'http://localhost:80/rest%s' % discussion_url)
+        assert_equal(r['discussion_thread']['_id'], discussion_url.split('/')[-2])
         self.app.post('/wiki/Home/attach', upload_files=[('file_info', '__init__.py', content),])
         r = self.app.get('/rest/p/test/wiki/Home/')
         r = json.loads(r.body)
-        assert_equal(len(r['page']['attachments']), 2)
+        assert_equal(len(r['attachments']), 2)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/0d1c69e8/ForgeWiki/forgewiki/wiki_main.py
----------------------------------------------------------------------
diff --git a/ForgeWiki/forgewiki/wiki_main.py b/ForgeWiki/forgewiki/wiki_main.py
index 66d01b7..94f98a5 100644
--- a/ForgeWiki/forgewiki/wiki_main.py
+++ b/ForgeWiki/forgewiki/wiki_main.py
@@ -736,7 +736,7 @@ class PageRestController(BaseController):
 
     @expose('json:')
     def index(self, **kw):
-        return dict(page=self.page)
+        return self.page.__json__()
 
 
 class WikiAdminController(DefaultAdminController):


[2/3] git commit: [#5652] ticket:325 added attachments info for Allura REST API

Posted by br...@apache.org.
[#5652]  ticket:325 added attachments info for Allura REST API


Project: http://git-wip-us.apache.org/repos/asf/incubator-allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-allura/commit/79e39b3c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/79e39b3c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/79e39b3c

Branch: refs/heads/master
Commit: 79e39b3cac09fdeca9af2a456330f367ede7930a
Parents: a211a0d
Author: Yuriy Arhipov <yu...@yandex.ru>
Authored: Tue May 7 01:44:48 2013 +0400
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Mon May 20 17:22:09 2013 +0000

----------------------------------------------------------------------
 Allura/allura/model/artifact.py                    |    5 ++-
 Allura/allura/model/discuss.py                     |    8 +++-
 ForgeTracker/forgetracker/model/ticket.py          |    5 ++
 .../forgetracker/tests/functional/test_root.py     |   38 +++++++++++++++
 ForgeWiki/forgewiki/tests/functional/test_root.py  |   20 ++++++--
 ForgeWiki/forgewiki/wiki_main.py                   |   13 ++++-
 6 files changed, 81 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/79e39b3c/Allura/allura/model/artifact.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/artifact.py b/Allura/allura/model/artifact.py
index 4a7f2c1..a8f573c 100644
--- a/Allura/allura/model/artifact.py
+++ b/Allura/allura/model/artifact.py
@@ -19,6 +19,8 @@ import logging
 import cPickle as pickle
 from collections import defaultdict
 from datetime import datetime
+from urlparse import urljoin
+from tg import config
 
 import bson
 import pymongo
@@ -96,7 +98,8 @@ class Artifact(MappedClass):
             labels=self.labels,
             related_artifacts=[a.url() for a in self.related_artifacts()],
             discussion_thread=self.discussion_thread,
-            discussion_thread_url=self.discussion_thread.url(),
+            discussion_thread_url=urljoin(config.get('base_url', 'http://sourceforge.net/'),
+                                          '/rest%s' % self.discussion_thread.url()),
         )
 
     def parent_security_context(self):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/79e39b3c/Allura/allura/model/discuss.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/discuss.py b/Allura/allura/model/discuss.py
index 4375077..e1da83c 100644
--- a/Allura/allura/model/discuss.py
+++ b/Allura/allura/model/discuss.py
@@ -21,6 +21,8 @@ from datetime import datetime
 import pymongo
 from pymongo.errors import DuplicateKeyError
 from pylons import tmpl_context as c, app_globals as g
+from urlparse import urljoin
+from tg import config
 
 from ming import schema
 from ming.orm.base import session
@@ -163,7 +165,11 @@ class Thread(Artifact, ActivityObject):
             _id=self._id,
             discussion_id=str(self.discussion_id),
             subject=self.subject,
-            posts=[dict(slug=p.slug, subject=p.subject)
+            posts=[dict(slug=p.slug,
+                        subject=p.subject,
+                        attachments=[dict(bytes=attach.length,
+                                          url=urljoin(config.get('base_url', 'http://sourceforge.net/'),
+                                                      attach.url())) for attach in p.attachments])
                    for p in self.posts])
 
     @property

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/79e39b3c/ForgeTracker/forgetracker/model/ticket.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/model/ticket.py b/ForgeTracker/forgetracker/model/ticket.py
index 45bef8b..00851bc 100644
--- a/ForgeTracker/forgetracker/model/ticket.py
+++ b/ForgeTracker/forgetracker/model/ticket.py
@@ -25,6 +25,8 @@ import pymongo
 from pymongo.errors import OperationFailure
 from pylons import tmpl_context as c, app_globals as g
 from pprint import pformat
+from urlparse import urljoin
+from tg import config as tg_config
 
 from ming import schema
 from ming.utils import LazyProperty
@@ -734,6 +736,9 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
             assigned_to_id=self.assigned_to_id and str(self.assigned_to_id) or None,
             status=self.status,
             private=self.private,
+            attachments=[dict(bytes=attach.length,
+                              url=urljoin(tg_config.get('base_url', 'http://sourceforge.net/'),
+                                          attach.url())) for attach in self.attachments],
             custom_fields=self.custom_fields)
 
     @classmethod

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/79e39b3c/ForgeTracker/forgetracker/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index 6723778..bf498be 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -1694,6 +1694,44 @@ class TestFunctionalController(TrackerTestController):
         r = self.app.get('/p/test/bugs/tags?term=')
         assert_equal(json.loads(r.body), [])
 
+    def test_rest_tickets(self):
+        ticket_view = self.new_ticket(summary='test').follow()
+        for f in ticket_view.html.findAll('form'):
+            if f.get('action', '').endswith('/post'):
+                break
+        params = dict()
+        inputs = f.findAll('input')
+        for field in inputs:
+            if field.has_key('name'):
+                params[field['name']] = field.has_key('value') and field['value'] or ''
+        params[f.find('textarea')['name']] = 'test comment'
+        self.app.post(f['action'].encode('utf-8'), params=params,
+                          headers={'Referer': '/bugs/1/'.encode("utf-8")})
+        r = self.app.get('/bugs/1/', dict(page=1))
+        post_link = str(r.html.find('div', {'class':'edit_post_form reply'}).find('form')['action'])
+        self.app.post(post_link + 'attach',
+                          upload_files=[('file_info', 'test.txt', 'test attach')])
+        r = self.app.get('/p/test/bugs/1/')
+        discussion_url = r.html.findAll('form')[-1]['action'][:-4]
+        r = self.app.get('/rest/p/test/bugs/1/')
+        r = json.loads(r.body)
+        assert_equal(r['ticket']['discussion_thread_url'],'http://localhost/rest%s' % discussion_url)
+        slug = r['ticket']['discussion_thread']['posts'][0]['slug']
+        assert_equal(r['ticket']['discussion_thread']['posts'][0]['attachments'][0]['url'],
+                     'http://localhost%s%s/attachment/test.txt' % (discussion_url, slug))
+        assert_equal(r['ticket']['discussion_thread']['posts'][0]['attachments'][0]['bytes'], 11)
+
+        file_name = 'test_root.py'
+        file_data = file(__file__).read()
+        upload = ('attachment', file_name, file_data)
+        r = self.app.post('/bugs/1/update_ticket',{
+            'summary':'test rest attach'
+        }, upload_files=[upload]).follow()
+        r = self.app.get('/rest/p/test/bugs/1/')
+        r = json.loads(r.body)
+        assert_equal(r['ticket']['attachments'][0]['url'], 'http://localhost/p/test/bugs/1/attachment/test_root.py')
+
+
 
 class TestMilestoneAdmin(TrackerTestController):
     def _post(self, params, **kw):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/79e39b3c/ForgeWiki/forgewiki/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/ForgeWiki/forgewiki/tests/functional/test_root.py b/ForgeWiki/forgewiki/tests/functional/test_root.py
index 49a39e8..d943530 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_root.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_root.py
@@ -20,6 +20,7 @@
 import os
 import Image, StringIO
 import allura
+import json
 
 from nose.tools import assert_true, assert_equal, assert_in
 
@@ -216,15 +217,15 @@ class TestRootController(TestController):
         response = self.app.get('/wiki/tést/history')
         assert 'tést' in response
         # two revisions are shown
-        assert '2 by Test Admin (test-admin)' in response
-        assert '1 by Test Admin (test-admin)' in response
+        assert '2 by Test Admin' in response
+        assert '1 by Test Admin' in response
         # you can revert to an old revison, but not the current one
         assert response.html.find('a',{'href':'./revert?version=1'})
         assert not response.html.find('a',{'href':'./revert?version=2'})
         response = self.app.get('/wiki/tést/history', extra_environ=dict(username='*anonymous'))
         # two revisions are shown
-        assert '2 by Test Admin (test-admin)' in response
-        assert '1 by Test Admin (test-admin)' in response
+        assert '2 by Test Admin' in response
+        assert '1 by Test Admin' in response
         # you cannot revert to any revision
         assert not response.html.find('a',{'href':'./revert?version=1'})
         assert not response.html.find('a',{'href':'./revert?version=2'})
@@ -620,3 +621,14 @@ class TestRootController(TestController):
     def test_user_browse_page(self):
         r = self.app.get('/wiki/browse_pages/')
         assert '<td>Test Admin (test-admin)</td>' in r
+
+    def test_rest_wiki(self):
+        r = self.app.get('/p/test/wiki/Home/')
+        discussion_url = r.html.findAll('form')[2]['action'][:-4]
+        content = file(__file__).read()
+        self.app.post('/wiki/Home/attach', upload_files=[('file_info', 'test_root.py', content)])
+        r = self.app.get('/rest/p/test/wiki/Home/')
+        r = json.loads(r.body)
+        assert_equal(r['attachments'][0]['url'], 'http://localhost/p/test/wiki/Home/attachment/test_root.py')
+        assert_equal(r['discussion_thread_url'], 'http://localhost/rest%s' % discussion_url)
+        assert_equal(r['discussion_thread']['_id'], discussion_url.split('/')[-2])

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/79e39b3c/ForgeWiki/forgewiki/wiki_main.py
----------------------------------------------------------------------
diff --git a/ForgeWiki/forgewiki/wiki_main.py b/ForgeWiki/forgewiki/wiki_main.py
index 0f5151e..1dc9e06 100644
--- a/ForgeWiki/forgewiki/wiki_main.py
+++ b/ForgeWiki/forgewiki/wiki_main.py
@@ -22,7 +22,7 @@ from urllib import unquote
 from datetime import datetime
 
 # Non-stdlib imports
-from tg import expose, validate, redirect, response, flash
+from tg import expose, validate, redirect, response, flash, config
 from tg.decorators import with_trailing_slash, without_trailing_slash
 from tg.controllers import RestController
 from pylons import tmpl_context as c, app_globals as g
@@ -30,6 +30,7 @@ from pylons import request
 from formencode import validators
 from webob import exc
 from ming.orm import session
+from urlparse import urljoin
 
 # Pyforge-specific imports
 from allura import model as M
@@ -697,7 +698,15 @@ class RootRestController(RestController):
         if page is None:
             raise exc.HTTPNotFound, title
         require_access(page, 'read')
-        return dict(title=page.title, text=page.text, labels=page.labels)
+        return dict(title=page.title,
+                    text=page.text,
+                    labels=page.labels,
+                    discussion_thread=page.discussion_thread,
+                    discussion_thread_url=urljoin(config.get('base_url', 'http://sourceforge.net/'),
+                                                  '/rest%s' % page.discussion_thread.url()),
+                    attachments=[dict(bytes=attach.length,
+                                      url=urljoin(config.get('base_url', 'http://sourceforge.net/'),
+                                                  attach.url())) for attach in page.attachments])
 
     @h.vardec
     @expose()