...
 
Commits (15)
......@@ -2,7 +2,7 @@
## Documentation
If you want to write an application for GangGo checkout our [API documentation page](https://ganggo.github.io/api/index.html).
If you want to write an application for GangGo checkout our [API documentation page](https://ganggo.git.feneas.org/documentation/development.html).
### Generate
......
package api
// Required for vendoring see golang.org/issue/13832
This diff is collapsed.
......@@ -19,10 +19,10 @@ package controllers
import (
"github.com/revel/revel"
"gopkg.in/ganggo/api.v0/app/helpers"
"gopkg.in/ganggo/ganggo.v0/app/jobs"
federation "gopkg.in/ganggo/federation.v0"
"gopkg.in/ganggo/ganggo.v0/app/models"
"git.feneas.org/ganggo/api/app/helpers"
"git.feneas.org/ganggo/ganggo/app/jobs"
run "github.com/revel/modules/jobs/app/jobs"
"git.feneas.org/ganggo/ganggo/app/models"
"net/http"
)
......@@ -165,16 +165,16 @@ func (a ApiAspect) CreatePerson() revel.Result {
return a.ApiError(http.StatusNotFound, ERR_NOT_FOUND)
}
dispatcher := jobs.Dispatcher{
User: a.CurrentUser,
Message: federation.EntityContact{
Author: a.CurrentUser.Person.Author,
Recipient: person.Author,
Sharing: true,
Following: true,
},
// check if that is the first entry
// if so push it to the network
var aspects models.Aspects
err = aspects.FindByUserPersonID(a.CurrentUser.ID, person.ID)
if len(aspects) == 0 {
run.Now(jobs.Dispatcher{
User: a.CurrentUser,
Message: membership,
})
}
go dispatcher.Run()
err = membership.Create()
if err != nil {
......@@ -256,17 +256,16 @@ func (a ApiAspect) DeletePerson() revel.Result {
return a.ApiError(http.StatusNotFound, ERR_NOT_FOUND)
}
dispatcher := jobs.Dispatcher{
User: a.CurrentUser,
Message: federation.EntityContact{
Author: a.CurrentUser.Person.Author,
Recipient: person.Author,
Sharing: false,
Following: false,
},
// check if that was the last entry
// if so push it to the network
var aspects models.Aspects
err = aspects.FindByUserPersonID(a.CurrentUser.ID, person.ID)
if len(aspects) == 0 {
run.Now(jobs.Dispatcher{
User: a.CurrentUser,
Message: membership,
})
}
go dispatcher.Run()
return a.RenderJSON(membership)
}
......
......@@ -20,7 +20,7 @@ package controllers
import (
"net/http"
"github.com/revel/revel"
"gopkg.in/ganggo/ganggo.v0/app/models"
"git.feneas.org/ganggo/ganggo/app/models"
)
const (
......@@ -48,6 +48,13 @@ type ApiError struct {
Error string `json:"error"`
}
func (c ApiHelper) RenderJSONLD(v interface{}) revel.Result {
c.Response.ContentType = "application/ld+json"
c.Response.Out.Header().Add(
"Accept", `application/ld+json; profile="https://www.w3.org/ns/activitystreams"`)
return c.RenderJSON(v)
}
func (c ApiHelper) CatchAll() revel.Result {
return c.ApiError(http.StatusNotImplemented, ERR_NOT_IMPLEMENTED)
}
......
......@@ -19,12 +19,12 @@ package controllers
import (
"github.com/revel/revel"
"gopkg.in/ganggo/ganggo.v0/app/models"
"gopkg.in/ganggo/ganggo.v0/app/jobs"
"gopkg.in/ganggo/api.v0/app/helpers"
"git.feneas.org/ganggo/ganggo/app/models"
"git.feneas.org/ganggo/ganggo/app/jobs"
"git.feneas.org/ganggo/api/app/helpers"
// XXX only for uuid
uuid "gopkg.in/ganggo/ganggo.v0/app/helpers"
federation "gopkg.in/ganggo/federation.v0"
uuid "git.feneas.org/ganggo/ganggo/app/helpers"
run "github.com/revel/modules/jobs/app/jobs"
"strconv"
"net/http"
)
......@@ -236,32 +236,24 @@ func (c ApiComment) CreatePost() revel.Result {
return c.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
entityComment := federation.EntityComment{
Author: c.CurrentUser.Person.Author,
comment := models.Comment{
Guid: guid,
ParentGuid: post.Guid,
Text: text,
ShareableID: post.ID,
ShareableType: models.ShareablePost,
PersonID: c.CurrentUser.Person.ID,
}
var comment models.Comment
err = comment.Create(&entityComment)
err = comment.Create()
if err != nil {
c.Log.Error(TAG, "db", err, "api", ERR_SERVER)
return c.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
entityComment.CreatedAt.New(comment.CreatedAt)
dispatcher := jobs.Dispatcher{
User: c.CurrentUser,
Model: comment,
Message: entityComment,
}
// XXX
// notify local user about a new comment
//go like.TriggerNotification(parentUser)
// deliver to the network
go dispatcher.Run()
run.Now(jobs.Dispatcher{User: c.CurrentUser, Message: comment})
// XXX
// notify local user about a new comment
//go like.TriggerNotification(parentUser)
return c.RenderJSON(comment)
}
......@@ -313,12 +305,8 @@ func (c ApiComment) Delete(guid string) revel.Result {
}
if comment.Person.ID == c.CurrentUser.Person.ID {
entity := federation.EntityRetraction{
Author: c.CurrentUser.Person.Author,
TargetGuid: comment.Guid,
TargetType: models.ShareableComment,
}
dispatcher := jobs.Dispatcher{Message: entity}
dispatcher := jobs.Dispatcher{
User: c.CurrentUser, Retract: true, Message: comment}
// NOTE relay to other hosts if we own this entity
// should be done before we start deleting db records
// thats why this call is synchron XXX we should
......
......@@ -28,4 +28,5 @@ func init() {
revel.InterceptMethod((*ApiAspect).checkUser, revel.BEFORE)
revel.InterceptMethod((*ApiNotification).checkUser, revel.BEFORE)
revel.InterceptMethod((*ApiOAuth).checkUser, revel.BEFORE)
revel.InterceptMethod((*ApiUserStream).checkUser, revel.BEFORE)
}
......@@ -19,10 +19,10 @@ package controllers
import (
"github.com/revel/revel"
"gopkg.in/ganggo/ganggo.v0/app/models"
"gopkg.in/ganggo/ganggo.v0/app/jobs"
"gopkg.in/ganggo/ganggo.v0/app/helpers"
federation "gopkg.in/ganggo/federation.v0"
"git.feneas.org/ganggo/ganggo/app/models"
"git.feneas.org/ganggo/ganggo/app/jobs"
"git.feneas.org/ganggo/ganggo/app/helpers"
run "github.com/revel/modules/jobs/app/jobs"
"net/http"
"strconv"
)
......@@ -163,7 +163,6 @@ func (l ApiLike) Create() revel.Result {
var (
postID uint
post models.Post
like models.Like
positive bool
)
......@@ -182,31 +181,24 @@ func (l ApiLike) Create() revel.Result {
return l.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
entityLike := federation.EntityLike{
like := models.Like{
Positive: positive,
ShareableID: post.ID,
PersonID: l.CurrentUser.Person.ID,
Guid: guid,
Author: l.CurrentUser.Person.Author,
ParentType: models.ShareablePost,
ParentGuid: post.Guid,
ShareableType: models.ShareablePost,
}
err = like.Create(&entityLike)
err = like.Create()
if err != nil {
l.Log.Error(TAG, "db", err, "api", ERR_SERVER)
return l.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
dispatcher := jobs.Dispatcher{
User: l.CurrentUser,
Model: like,
Message: entityLike,
}
// XXX
// notify local user about a new comment
//go like.TriggerNotification(parentUser)
// deliver to the network
go dispatcher.Run()
run.Now(jobs.Dispatcher{User: l.CurrentUser, Message: like})
// XXX
// notify local user about a new comment
//go like.TriggerNotification(parentUser)
return l.RenderJSON(like)
}
......@@ -265,12 +257,8 @@ func (l ApiLike) Delete(guid string) revel.Result {
}
if like.PersonID == l.CurrentUser.Person.ID {
entity := federation.EntityRetraction{
Author: l.CurrentUser.Person.Author,
TargetGuid: like.Guid,
TargetType: models.ShareableLike,
}
dispatcher := jobs.Dispatcher{Message: entity}
dispatcher := jobs.Dispatcher{
User: l.CurrentUser, Retract: true, Message: like}
// NOTE relay to other hosts if we own this entity
// should be done before we start deleting db records
// thats why this call is synchron XXX we should
......
......@@ -19,8 +19,8 @@ package controllers
import (
"github.com/revel/revel"
"gopkg.in/ganggo/api.v0/app/helpers"
"gopkg.in/ganggo/ganggo.v0/app/models"
"git.feneas.org/ganggo/api/app/helpers"
"git.feneas.org/ganggo/ganggo/app/models"
"net/http"
)
......
......@@ -19,9 +19,9 @@ package controllers
import (
"github.com/revel/revel"
"gopkg.in/ganggo/ganggo.v0/app/models"
"gopkg.in/ganggo/ganggo.v0/app/helpers"
apiHelpers "gopkg.in/ganggo/api.v0/app/helpers"
"git.feneas.org/ganggo/ganggo/app/models"
"git.feneas.org/ganggo/ganggo/app/helpers"
apiHelpers "git.feneas.org/ganggo/api/app/helpers"
"net/http"
)
......
......@@ -19,7 +19,7 @@ package controllers
import (
"github.com/revel/revel"
"gopkg.in/ganggo/ganggo.v0/app/models"
"git.feneas.org/ganggo/ganggo/app/models"
"net/http"
)
......
......@@ -21,11 +21,11 @@ import (
"time"
"github.com/revel/revel"
"strconv"
apiHelpers "gopkg.in/ganggo/api.v0/app/helpers"
"gopkg.in/ganggo/ganggo.v0/app/helpers"
"gopkg.in/ganggo/ganggo.v0/app/models"
"gopkg.in/ganggo/ganggo.v0/app/jobs"
federation "gopkg.in/ganggo/federation.v0"
apiHelpers "git.feneas.org/ganggo/api/app/helpers"
"git.feneas.org/ganggo/ganggo/app/helpers"
"git.feneas.org/ganggo/ganggo/app/models"
"git.feneas.org/ganggo/ganggo/app/jobs"
run "github.com/revel/modules/jobs/app/jobs"
"net/http"
)
......@@ -89,7 +89,7 @@ type ApiPost struct {
*/
func (p ApiPost) Index() revel.Result {
var (
offset int
offset uint
fields string
visibility int
posts models.Posts
......@@ -170,7 +170,6 @@ func (p ApiPost) Index() revel.Result {
*/
func (p ApiPost) Create() revel.Result {
var (
post models.Post
postText, fields string
aspectID uint
)
......@@ -191,27 +190,21 @@ func (p ApiPost) Create() revel.Result {
return p.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
entity := federation.EntityStatusMessage{
Text: postText,
Author: p.CurrentUser.Person.Author,
post := models.Post{
CreatedAt: time.Now(),
Public: aspectID <= 0,
Guid: guid,
ProviderName: "GangGo",
Public: true,
}
entity.CreatedAt.New(time.Now())
// this one is a private message
if aspectID > 0 {
entity.Public = false
Type: models.StatusMessage,
Text: postText,
PersonID: p.CurrentUser.Person.ID,
}
// save post locally
err = post.Create(&entity)
err = post.Create()
if err != nil {
p.Log.Error(TAG, "db", err, "api", ERR_SERVER)
return p.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
if entity.Public == false {
if !post.Public {
// this is required for mapping
// posts to the author
shareable := models.Shareable{
......@@ -236,12 +229,8 @@ func (p ApiPost) Create() revel.Result {
}
}
dispatcher := jobs.Dispatcher{
User: p.CurrentUser,
Message: entity,
Model: post,
}
go dispatcher.Run()
// federate all the things \m/
run.Now(jobs.Dispatcher{User: p.CurrentUser, Message: post})
return p.RenderJSON(
apiHelpers.SelectStructFields(post, fields))
......@@ -361,15 +350,8 @@ func (p ApiPost) Delete(guid string) revel.Result {
}
if post.Person.ID == p.CurrentUser.Person.ID {
entity := federation.EntityRetraction{
Author: p.CurrentUser.Person.Author,
TargetGuid: post.Guid,
TargetType: models.ShareablePost,
}
dispatcher := jobs.Dispatcher{
User: p.CurrentUser,
Message: entity,
}
User: p.CurrentUser, Retract: true, Message: post}
// NOTE relay to other hosts if we own this entity
// should be done before we start deleting db records
// thats why this call is synchron XXX we should
......@@ -455,26 +437,22 @@ func (p ApiPost) Reshare() revel.Result {
return p.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
entity := federation.EntityReshare{
Author: p.CurrentUser.Person.Author,
post := models.Post{
PersonID: p.CurrentUser.Person.ID,
CreatedAt: time.Now(),
Public: true, // reshare is always public
Guid: guid,
RootAuthor: rootPost.Person.Author,
RootGuid: rootPost.Guid,
Type: models.Reshare,
RootPersonID: rootPost.Person.ID,
RootGuid: &rootPost.Guid,
}
entity.CreatedAt.New(time.Now())
var post models.Post
err = post.Create(&entity)
err = post.Create()
if err != nil {
p.Log.Error(TAG, "db", err, "api", ERR_SERVER)
return p.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
dispatcher := jobs.Dispatcher{
User: p.CurrentUser,
Model: post,
Message: entity,
}
go dispatcher.Run()
run.Now(jobs.Dispatcher{User: p.CurrentUser, Message: post})
return p.RenderJSON(post)
}
......@@ -19,7 +19,7 @@ package controllers
import (
"github.com/revel/revel"
"gopkg.in/ganggo/ganggo.v0/app/models"
"git.feneas.org/ganggo/ganggo/app/models"
"net/http"
)
......
......@@ -20,7 +20,7 @@ package controllers
import (
"net/http"
"github.com/revel/revel"
"gopkg.in/ganggo/ganggo.v0/app/jobs"
"git.feneas.org/ganggo/ganggo/app/jobs"
)
/**
......
package controllers
//
// GangGo API Library
// Copyright (C) 2017 Lukas Matt <lukas@zauberstuhl.de>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
import (
"net/http"
"git.feneas.org/ganggo/ganggo/app/models"
"git.feneas.org/ganggo/api/app/helpers"
apiHelpers "git.feneas.org/ganggo/api/app/helpers"
"github.com/revel/revel"
"strconv"
)
/**
* @apiDefine UserStreams UserStreams endpoint
*
* Viewing, creating and deleting UserStream structures
*/
type ApiUserStream struct {
ApiHelper
}
/**
* @api {post} /users/streams Create a new user stream
* @apiName ApiUserStream.Create
* @apiGroup UserStreams
*
* @apiParam {String} access_token Oauth access token
* @apiParam {String} name The name of stream
* @apiParam {String} [tags] Tags separated by ","
* @apiParam {String} [people] Author handle (e.g. lukas@sechat.org) separated by ","
* @apiParam {String} [expression] Regular expression
*
* @apiSuccess {Number} UserID User database identifier
* @apiSuccess {String} Name User stream name
* @apiSuccess {String} Tags Tags separated by ","
* @apiSuccess {String} People People separated by ","
* @apiSuccess {String} Expression Regular Expression
*
* @apiSuccessExample {json} Success-Response
* HTTP/1.1 200 OK
* {
* "UserID": 1,
* "Name": "Test",
* "Tags": "linux,software,opensource",
* "People": "lukas@sechat.org,hq@ggg.social",
* "Expression": "ganggo|socialhome"
* }
*
* @apiError (Errors) {String} error Contains the recent error message
*
* @apiErrorExample {json} BadRequest
* HTTP/1.1 400 Bad Request
* {
* "error": "[...]"
* }
*
* @apiErrorExample {json} Unauthorized
* HTTP/1.1 401 Unauthorized
* {
* "error": "[...]"
* }
*
* @apiErrorExample {json} ServerError
* HTTP/1.1 500 Internal Server Error
* {
* "error": "[...]"
* }
*
*/
func (s ApiUserStream) Create(name, tags, people, expression string) revel.Result {
if helpers.EmptyString(name) {
s.Log.Error(TAG, "api", ERR_EMPTY_STRING)
return s.ApiError(http.StatusBadRequest, ERR_EMPTY_STRING)
}
stream := models.UserStream{
UserID: s.CurrentUser.ID,
Name: name,
Tags: tags,
People: people,
Expression: expression,
}
err := stream.Create()
if err != nil {
s.Log.Error(TAG, "db", err, "api", ERR_SERVER)
return s.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
return s.RenderJSON(stream)
}
/**
* @api {delete} /users/streams/:id Delete a user stream
* @apiName ApiUserStream.Delete
* @apiGroup UserStreams
*
* @apiParam {String} access_token Oauth access token
* @apiParam {Number} id The database identifier for the struct
*
* @apiSuccessExample {json} Success-Response
* HTTP/1.1 200 OK
* {}
*
* @apiError (Errors) {String} error Contains the recent error message
*
* @apiErrorExample {json} BadRequest
* HTTP/1.1 400 Bad Request
* {
* "error": "[...]"
* }
*
* @apiErrorExample {json} Unauthorized
* HTTP/1.1 401 Unauthorized
* {
* "error": "[...]"
* }
*
*/
func (s ApiUserStream) Delete(id uint) revel.Result {
userStream := models.UserStream{
ID: id,
UserID: s.CurrentUser.ID,
}
err := userStream.Delete()
if err != nil {
s.Log.Error(TAG, "db", err, "api", ERR_BAD_REQUEST)
return s.ApiError(http.StatusBadRequest, ERR_BAD_REQUEST)
}
return s.RenderJSON(struct{}{})
}
/**
* @api {get} /people/:guid/stream Fetch person stream
* @apiName ApiUserStream.ShowPersonStream
* @apiGroup UserStreams
*
* @apiParam {String} guid Unique global or database ID
* @apiParam {Number} [offset] Post offset for database
* @apiParam {String} [fields] Display only specific fields, e.g. fields=ID,Person(ID:Profile(ID:ImageUrl)). This will only work on standard format!
* @apiParam {String} [format] On default we will use the standard GangGo output but for compatibility reasons you can choose format "diaspora" as well
*
* @apiSuccessExample {json} Success-Response (format=default)
* HTTP/1.1 200 OK
* {
* "0": {
* "Guid": "5b5d5b4f7044e3444db73504e8b08be8",
* "ID": 20,
* "Text": "hi whats up?\r\n\r\n",
* [...]
* }
* }
*
* @apiSuccessExample {json} Success-Response (format=diaspora)
* HTTP/1.1 200 OK
* [
* {
* "public": true,
* "guid": "abe68905a61297a686d675796d6b5169",
* "author": {
* "id": 1,
* "guid": "bb9e7958aa201ffbd47852fe83e1a1fa"
* },
* "post_type": "StatusMessage",
* "text": "a public post",
* "provider_display_name": "GangGo",
* "created_at": "2018-02-03T23:47:35.168488+01:00"
* }
* ]
*
* @apiError (Errors) {String} error Contains the recent error message
*
* @apiErrorExample {json} Unauthorized
* HTTP/1.1 401 Unauthorized
* {
* "error": "[...]"
* }
*
* @apiErrorExample {json} NotFound
* HTTP/1.1 404 Not Found
* {
* "error": "[...]"
* }
*
* @apiErrorExample {json} ServerError
* HTTP/1.1 500 Internal Server Error
* {
* "error": "[...]"
* }
*
*/
func (s ApiUserStream) ShowPersonStream(guid, fields string, offset uint) revel.Result {
var person models.Person
personID, err := strconv.ParseUint(guid, 10, 32);
if err == nil {
err = person.FindByID(uint(personID))
} else {
err = person.FindByGuid(guid)
}
if err != nil {
s.Log.Error(TAG, "db", err, "api", ERR_NOT_FOUND)
return s.ApiError(http.StatusNotFound, ERR_NOT_FOUND)
}
var posts models.Posts
err = posts.FindAllByUserAndPersonID(s.CurrentUser, person.ID, offset)
if err != nil {
s.Log.Error(TAG, "db", err, "api", ERR_SERVER)
return s.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
var format string
s.Params.Bind(&format, "format")
if format == "diaspora" {
diasporaPosts := apiHelpers.DiasporaPosts{}
diasporaPosts.Cast(posts)
return s.RenderJSON(diasporaPosts)
}
return s.RenderJSON(
helpers.SelectStructFields(posts, fields))
}
// This will overwrite APIHelper checkUser and
// skip authentication on ApiOAuth.Create
func (s *ApiUserStream) checkUser() revel.Result {
args := make(map[string]string)
route := revel.MainRouter.Reverse("ApiUserStream.ShowPersonStream", args)
if route != nil && route.URL == s.Request.URL.Path {
return nil
}
return s.ApiHelper.checkUser()
}
package helpers
//
// GangGo API Library
// Copyright (C) 2017 Lukas Matt <lukas@zauberstuhl.de>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
import (
"time"
"git.feneas.org/ganggo/ganggo/app/models"
)
// NOTE Unfortunately diaspora requires a different JSON
// format diasporaPosts will simply change the
// struct tags to the accepted format
type diasporaPerson struct{
ID uint `json:"id"`
Guid string `json:"guid"`
}
type diasporaPost struct{
Public bool `json:"public"`
Guid string `json:"guid"`
Person diasporaPerson `json:"author"`
Type string `json:"post_type"`
Text string `json:"text"`
ProviderName string `json:"provider_display_name"`
CreatedAt time.Time `json:"created_at"`
}
type DiasporaPosts []diasporaPost
func (dPosts *DiasporaPosts) Cast(posts models.Posts) {
for _, post := range posts {
*dPosts = append(*dPosts, diasporaPost{
Public: post.Public,
Guid: post.Guid,
Person: diasporaPerson{
ID: post.Person.ID,
Guid: post.Person.Guid,
},
Type: post.Type,
Text: post.Text,
ProviderName: post.ProviderName,
CreatedAt: post.CreatedAt,
})
}
}
......@@ -8,8 +8,19 @@ import (
"github.com/revel/revel"
)
var (
API_VERSION string
PROTO string
ADDRESS string
)
func init() {
revel.OnAppStart(func() {
revel.Config.SetSection("ganggo")
API_VERSION = revel.Config.StringDefault("api.version", "v0")
PROTO = revel.Config.StringDefault("proto", "http://")
ADDRESS = revel.Config.StringDefault("address", "localhost")
revel.INFO.Println("Restful API loaded.")
})
}
# Restful API routes
## ActivityPub
POST /api/v0/ap/inbox ApiApUser.Inbox
* /api/v0/ap/user/:username/outbox ApiApUser.Outbox
POST /api/v0/ap/user/:username/inbox ApiApUser.Inbox
* /api/v0/ap/user/:username/following ApiApUser.Following
* /api/v0/ap/user/:username/followers ApiApUser.Followers
* /api/v0/ap/user/:username/actor ApiApUser.Actor
## GangGo API
POST /api/v0/oauth/tokens ApiOAuth.Create
DELETE /api/v0/oauth/tokens/:id ApiOAuth.Delete
......@@ -10,6 +19,9 @@ GET /api/v0/posts/:guid ApiPost.Show
DELETE /api/v0/posts/:guid ApiPost.Delete
POST /api/v0/posts/:guid/reshare ApiPost.Reshare
POST /api/v0/users/streams ApiUserStream.Create
DELETE /api/v0/users/streams/:id ApiUserStream.Delete
GET /api/v0/notifications ApiNotification.Index
PUT /api/v0/notifications/:id ApiNotification.Update
......@@ -33,6 +45,8 @@ GET /api/v0/people/:id/profile ApiProfile.Show
#POST /api/v0/people/:id/profile ApiProfile.Create
#DELETE /api/v0/people/:id/profile ApiProfile.Delete
GET /api/v0/people/:guid/stream ApiUserStream.ShowPersonStream
GET /api/v0/aspects ApiAspect.Index
POST /api/v0/aspects ApiAspect.Create
#GET /api/v0/aspects/:id ApiAspect.Show
......