...
 
Commits (1)
......@@ -36,6 +36,7 @@ const (
ERR_BAD_REQUEST = "Bad request"
ERR_NOT_FOUND = "Not found"
ERR_NOT_IMPLEMENTED = "Not implemented"
ERR_INVALID_DATETIME = "Invalid datetime"
)
type ApiHelper struct {
......
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"
"github.com/revel/revel"
"gopkg.in/ganggo/ganggo.v0/app/models"
"gopkg.in/ganggo/api.v0/app/helpers"
)
/**
* @apiDefine Calendar endpoint
*
* Create, delete and find calendar events
*/
type ApiCalendar struct {
*revel.Controller
ApiHelper
}
/**
* @api {post} /search Discover a new person
* @apiName ApiSearch.Create
* @apiGroup Search
*
* @apiParam {String} handle Person network handle
* @apiParam {String} access_token Oauth access token
*
* @apiSuccess {String} CreatedAt Timestamp of creation
* @apiSuccess {String} UpdatedAt Timestamp of last replacment
* @apiSuccess {Number} ID Unique database ID
* @apiSuccess {String} Guid Person global ID
* @apiSuccess {String} Author Handle with TLD
* @apiSuccess {String} SerializedPublicKey Public key
* @apiSuccess {Number} UserID User database ID (null if not a local user)
*
* @apiSuccessExample {json} Success-Response
* HTTP/1.1 200 OK
* {
* "ID": 12,
* "CreatedAt": "2018-01-08T15:25:43Z",
* "UpdatedAt": "2018-01-08T15:25:43Z",
* "Guid": "cc783a9749f09c7d817a1707a4c052bc",
* "Author": "test@localhost",
* "SerializedPublicKey": "[...]",
* "UserID": 1,
* }
*
* @apiError (Errors) {String} error Contains the recent error message
*
* @apiErrorExample {json} NotFound
* HTTP/1.1 404 Not Found
* {
* "error": "[...]"
* }
*
*/
func (c ApiCalendar) Create() revel.Result {
var (
name string
calendar models.Calendar
)
c.Params.Bind(&name, "name")
calendar.UserID = c.CurrentUser.ID
calendar.Name = name
if helpers.EmptyString(name) {
c.Log.Error(TAG, "api", ERR_EMPTY_STRING)
return c.ApiError(http.StatusBadRequest, ERR_EMPTY_STRING)
}
err := calendar.Create()
if err != nil {
c.Log.Error(TAG, "db", err, "api", ERR_SERVER)
return c.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
return c.RenderJSON(calendar)
}
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"
"github.com/revel/revel"
"gopkg.in/ganggo/ganggo.v0/app/helpers"
"gopkg.in/ganggo/ganggo.v0/app/models"
federation "gopkg.in/ganggo/federation.v0"
"time"
"strconv"
)
type ApiCalendarEvent struct {
*revel.Controller
ApiHelper
}
/**
* @api {post} /search Discover a new person
* @apiName ApiSearch.Create
* @apiGroup Search
*
* @apiParam {String} handle Person network handle
* @apiParam {String} access_token Oauth access token
*
* @apiSuccess {String} CreatedAt Timestamp of creation
* @apiSuccess {String} UpdatedAt Timestamp of last replacment
* @apiSuccess {Number} ID Unique database ID
* @apiSuccess {String} Guid Person global ID
* @apiSuccess {String} Author Handle with TLD
* @apiSuccess {String} SerializedPublicKey Public key
* @apiSuccess {Number} UserID User database ID (null if not a local user)
*
* @apiSuccessExample {json} Success-Response
* HTTP/1.1 200 OK
* {
* "ID": 12,
* "CreatedAt": "2018-01-08T15:25:43Z",
* "UpdatedAt": "2018-01-08T15:25:43Z",
* "Guid": "cc783a9749f09c7d817a1707a4c052bc",
* "Author": "test@localhost",
* "SerializedPublicKey": "[...]",
* "UserID": 1,
* }
*
* @apiError (Errors) {String} error Contains the recent error message
*
* @apiErrorExample {json} NotFound
* HTTP/1.1 404 Not Found
* {
* "error": "[...]"
* }
*
*/
func (p ApiCalendarEvent) Create() revel.Result {
var allDay bool
var description, summary string
var location, formStart, formEnd string
var calendarID, aspectID uint
p.Params.Bind(&allDay, "all_day")
p.Params.Bind(&description, "description")
p.Params.Bind(&summary, "summary")
p.Params.Bind(&formStart, "start")
p.Params.Bind(&formEnd, "end")
p.Params.Bind(&location, "location")
p.Params.Bind(&calendarID, "calendarID")
p.Params.Bind(&aspectID, "aspectID")
start, err := time.Parse(federation.TIME_FORMAT, formStart)
if err != nil {
p.Log.Error(TAG, "err", err, "api", ERR_INVALID_DATETIME)
return p.ApiError(http.StatusBadRequest, ERR_INVALID_DATETIME)
}
var end time.Time
if !allDay {
end, err = time.Parse(federation.TIME_FORMAT, formEnd)
if err != nil {
p.Log.Error(TAG, "err", err, "api", ERR_INVALID_DATETIME)
return p.ApiError(http.StatusBadRequest, ERR_INVALID_DATETIME)
}
}
guid, err := helpers.Uuid()
if err != nil {
p.Log.Error(TAG, "db", err, "api", ERR_SERVER)
return p.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
event := models.CalendarEvent{
PersonID: p.CurrentUser.Person.ID,
Guid: guid,
Start: start,
End: end,
AllDay: allDay,
Location: location,
Description: description,
Summary: summary,
}
if calendarID > 0 {
var calendar models.Calendar
err = calendar.FindByUserAndID(p.CurrentUser, calendarID)
if err != nil {
p.Log.Error(TAG, "err", err, "api", ERR_NOT_FOUND)
return p.ApiError(http.StatusNotFound, ERR_NOT_FOUND)
}
event.CalendarID = calendar.ID
} else {
event.Public = true
}
err = event.Create()
if err != nil {
p.Log.Error(TAG, "err", err, "api", ERR_SERVER)
return p.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
if aspectID > 0 {
shareable := models.Shareable{
ShareableID: event.ID,
UserID: p.CurrentUser.ID,
ShareableType: models.ShareableEvent,
}
if err := shareable.Create(); err != nil {
p.Log.Error(TAG, "db", err, "api", ERR_SERVER)
return p.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
// create an aspect visibility entry
// the host has to remember the recipients
visibility := models.AspectVisibility{
ShareableID: event.ID,
AspectID: aspectID,
ShareableType: models.ShareableEvent,
}
if err := visibility.Create(); err != nil {
p.Log.Error(TAG, "db", err, "api", ERR_SERVER)
return p.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
}
apiPost := ApiPost{p.Controller, p.ApiHelper}
apiPost.Params.Set("post", p.Message("calendars.preambel"))
apiPost.Params.Set("eventID",
strconv.FormatUint(uint64(event.ID), 10))
apiPost.Params.Set("aspectID",
strconv.FormatUint(uint64(aspectID), 10))
apiPost.Create()
return p.RenderJSON(event)
}
......@@ -28,4 +28,7 @@ func init() {
revel.InterceptMethod((*ApiAspect).checkUser, revel.BEFORE)
revel.InterceptMethod((*ApiNotification).checkUser, revel.BEFORE)
revel.InterceptMethod((*ApiOAuth).checkUser, revel.BEFORE)
revel.InterceptMethod((*ApiSearch).checkUser, revel.BEFORE)
revel.InterceptMethod((*ApiCalendar).checkUser, revel.BEFORE)
revel.InterceptMethod((*ApiCalendarEvent).checkUser, revel.BEFORE)
}
......@@ -202,9 +202,6 @@ func (l ApiLike) Create() revel.Result {
Message: entityLike,
}
// XXX
// notify local user about a new comment
//go like.TriggerNotification(parentUser)
// deliver to the network
go dispatcher.Run()
......
......@@ -172,12 +172,13 @@ func (p ApiPost) Create() revel.Result {
var (
post models.Post
postText, fields string
aspectID uint
aspectID, eventID uint
)
p.Params.Bind(&postText, "post")
p.Params.Bind(&fields, "fields")
p.Params.Bind(&aspectID, "aspectID")
p.Params.Bind(&eventID, "eventID")
if apiHelpers.EmptyString(postText) {
p.Log.Error(TAG, "api", ERR_EMPTY_STRING)
......@@ -191,12 +192,42 @@ func (p ApiPost) Create() revel.Result {
return p.ApiError(http.StatusInternalServerError, ERR_SERVER)
}
var entityEvent *federation.EntityEvent
if eventID > 0 {
var event models.CalendarEvent
err = event.FindByUserAndID(p.CurrentUser, eventID)
if err != nil {
p.Log.Error(TAG, "db", err, "api", ERR_NOT_FOUND)
return p.ApiError(http.StatusNotFound, ERR_NOT_FOUND)
}
var start, end federation.Time
start.New(event.Start)
end.New(event.End)
entityEvent = &federation.EntityEvent{
Author: event.Person.Profile.Author,
Guid: event.Guid,
Summary: event.Summary,
Start: start,
End: &end,
AllDay: event.AllDay,
Description: event.Description,
Location: &federation.EntityLocation{
// XXX we do not handle this right now
Lat: "0.0", Lng: "0.0",
Address: event.Location,
},
}
}
entity := federation.EntityStatusMessage{
Text: postText,
Author: p.CurrentUser.Person.Author,
Guid: guid,
ProviderName: "GangGo",
Public: true,
Event: entityEvent,
}
entity.CreatedAt.New(time.Now())
// this one is a private message
......
......@@ -3,6 +3,9 @@
POST /api/v0/oauth/tokens ApiOAuth.Create
DELETE /api/v0/oauth/tokens/:id ApiOAuth.Delete
POST /api/v0/calendar ApiCalendar.Create
POST /api/v0/calendar/events ApiCalendarEvent.Create
GET /api/v0/posts ApiPost.Index
POST /api/v0/posts ApiPost.Create
# both guid and uint are possible here
......