add some works

This commit is contained in:
inhosin 2019-09-07 17:54:53 +03:00
parent cd9ec0c774
commit 8807e5aaab
22 changed files with 1074 additions and 3 deletions

6
handlers/README.md Normal file
View file

@ -0,0 +1,6 @@
# Handlers
This folder contains [Mux](https://github.com/gorilla/mux) route handlers. If you've worked in webservers in other languages, it's similar to the concept of controllers.
It's common to see a handler take some information and spit it to something in `lib`. This is because handlers convert web-server knowledge to buisness-logic rather than do everything at once.

41
handlers/groups/get.go Normal file
View file

@ -0,0 +1,41 @@
package groups
import (
"fmt"
"git.macaw.me/inhosin/subhub/activitypub"
"git.macaw.me/inhosin/subhub/data"
"git.macaw.me/inhosin/subhub/data/models"
"git.macaw.me/inhosin/subhub/handlers"
"github.com/gin-gonic/gin"
"net/http"
)
// Get returns a Group
//
// Expects a `{name}` url variable
// in the route: `/api/group/:name`
func Get(c *gin.Context) {
name := c.Param("name")
if name == "" {
c.String(http.StatusBadRequest, "Bad request! No name in URL")
return
}
group, err := models.GetGroup(data.GetDB(), name)
if err != nil {
c.String(http.StatusInternalServerError, err.Error())
return
}
if group == nil {
c.String(http.StatusNotFound, fmt.Sprintf("%s does not exits on server", name))
return
}
url := handlers.GetFullHostName() + "/activity/group/" + group.Slug
actor := activitypub.NewPerson(url)
actor.PreferredUsername = group.Name
actor.Name = group.Name
actor.Summary = group.Note
c.JSON(http.StatusOK, actor)
}

32
handlers/groups/post.go Normal file
View file

@ -0,0 +1,32 @@
package groups
import (
"git.macaw.me/inhosin/subhub/data"
"git.macaw.me/inhosin/subhub/data/models"
"github.com/gin-gonic/gin"
"net/http"
)
type createGroupRequest struct {
Name string `json:"name"`
Note string `json:"note"`
}
type createGroupResponse struct {
Slug string `json:"slug"`
}
// Create adds an group to the database
func Create(c *gin.Context) {
var body createGroupRequest
c.BindJSON(&body)
db := data.GetDB()
slug, err := models.PutGroup(db, body.Name, body.Note)
if err != nil {
c.String(http.StatusInternalServerError, err.Error())
return
}
resp := createGroupResponse{Slug: slug}
c.JSON(http.StatusOK, resp)
}

7
handlers/path.go Normal file
View file

@ -0,0 +1,7 @@
package handlers
// GetFullHostName return string
func GetFullHostName() string {
// TODO make it at config
return "http://" + "localhost" + ":8090"
}

View file

@ -0,0 +1,23 @@
# What's Webfinger?
[Webfinger](https://en.wikipedia.org/wiki/WebFinger), a protocol for discovering objects on the server. It's used by Mastodon and is important for interop'ing with Mastodon (and most ActivityPub servers).
It lives at a special route: `GET /.well-known/webfinger`.
We can expect a webfinger response to always looks something like this:
```json
{
"subject": "acct:alice@my-example.com",
"links": [
{
"rel": "self",
"type": "application/activity+json",
"href": "https://my-example.com/actor"
}
]
}
```
In this case, `alice` is the ActivityPub Organization slug, and `my-example.com` is the domain of the server.

View file

@ -0,0 +1,40 @@
package webfinder
import (
"git.macaw.me/inhosin/subhub/handlers"
"net/mail"
"strings"
)
func newBadAddressError(address string) *badAddressError {
return &badAddressError{address: address}
}
func slugOf(address string) string {
fragment := strings.Split(address, "@")
return fragment[0]
}
func atAddress(address string) (*Resource, error) {
// foo@bar.org => foo
parser := mail.AddressParser{}
_, err := parser.Parse(address)
if err != nil {
return nil, newBadAddressError(address)
}
// foo@bar.org => foo
slug := slugOf(address)
domain := handlers.GetFullHostName()
return &Resource{
Subject: address,
Links: []Link{
{
Rel: "self",
Type: "application/activity+json",
HRef: domain + "/api/group/" + slug,
},
},
}, nil
}

View file

@ -0,0 +1,26 @@
package webfinder
type Resource struct {
Subject string `json:"subject,omitempty"`
Aliases []string `json:"aliases,omitempty"`
Properties map[string]string `json:"properties,omitempty"`
Links []Link `json:"links"`
}
type Link struct {
HRef string `json:"href"`
Type string `json:"type,omitempty"`
Rel string `json:"rel"`
Properties map[string]*string `json:"properties,omitempty"`
Titles map[string]string `json:"titles,omitempty"`
}
type Rel string
type badAddressError struct {
address string
}
func (e *badAddressError) Error() string {
return "badly formatted address: " + e.address
}

View file

@ -0,0 +1,50 @@
package webfinder
import (
"errors"
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
func Get(c *gin.Context) {
res := c.Query("resource")
if res == "" {
c.String(http.StatusBadRequest, "Missing 'resouce' query parameter in webfinger")
return
}
address, err := getAddress(res)
if err != nil {
c.String(http.StatusBadRequest, err.Error())
}
// TODO find group???
actor, err := atAddress(address)
if err != nil {
if _, ok := err.(*badAddressError); ok {
c.String(http.StatusBadRequest, "Incorrect address format")
return
}
c.String(http.StatusBadRequest, err.Error())
return
}
if actor == nil {
c.String(http.StatusBadRequest, "Account not found")
}
// bytes, err := json.Marshal(actor)
// if err != nil {
// http.Error(w, err.Error(), http.StatusBadRequest)
// return
// }
c.JSON(http.StatusOK, actor)
}
func getAddress(res string) (string, error) {
args := strings.Split(res, ":")
if args[0] != "acct" {
return "", errors.New("Resource didn`t start with acct")
}
return args[1], nil
}