Commit 148b0762 authored by zauberstuhl's avatar zauberstuhl

Initial commit

parents
# revel
test-results/
tmp/
routes/
# build
*.tar.gz
conf/app.conf
# assets
node_modules
public/assets
This diff is collapsed.
go := $(shell command -v go 2> /dev/null)
npm := $(shell command -v npm 2> /dev/null)
revel := $(shell command -v revel 2> /dev/null)
train := $(shell command -v train 2> /dev/null)
define install_deps_info
is not available please run 'make install-deps'
endef
define train_info
$(install_deps_info)
And don't forget to add the node modules to your path
e.g. export PATH=$$PATH:$$(pwd)/node_modules/.bin
endef
all: precompile compile
install-deps:
ifndef go
$(error "go is not available: https://golang.org/dl/")
endif
ifndef npm
$(error "npm is not available please install it first!")
endif
# Asset pipeline
npm install node-sass
npm install coffee-script
go get github.com/shaoshing/train
go build -o $(GOPATH)/bin/train github.com/shaoshing/train/cmd
# Revel web framework
go get github.com/revel/revel
go get github.com/revel/cmd/revel
# Document Parser
go get github.com/PuerkitoBio/goquery
# Bcrypt password hashing
go get golang.org/x/crypto/bcrypt
# ORM
go get github.com/jinzhu/gorm
set-env:
$(info $(env_info))
precompile:
ifndef train
$(error "train $(train_info)")
endif
train -out public -source app/assets
compile:
ifndef revel
$(error "revel $(install_deps_info)")
endif
revel package github.com/ganggo/ganggo
# GangGo - Diaspora in GoLang
This is the application server repository. Which is still
in pre-alpha state so please don't use it for production!
## Dependencies
For generating the required assets GangGo needs npm for `sass` and `coffee-script`
which works in combination with `github.com/shaoshing/train`
Following golang dependecnies are required for:
- the web framework `github.com/revel/revel`
- parsing documents e.g. hcard `github.com/PuerkitoBio/goquery`
- using password hashing `golang.org/x/crypto/bcrypt`
- support multiple databases `github.com/jinzhu/gorm`
All this can be installed via:
make install-deps
## Precompile and Build
Make sure your `node_modules/.bin` is in your `$PATH` variable e.g.:
export PATH=$PATH:$(pwd)/node_modules/.bin
Then run
make
## Development
If you don't want to compile the whole application everytime
you change something you can run it directly via
revel run github.com/ganggo/ganggo
Revel is able to watch changes and recompile if necessary!
### Assets
To recompile your assets in your development environment run
make precompile
(function(){
console.debug("Init GangGo JS");
$(".markdown").each(function(index) {
$(this).html(marked($(this).html()));
});
})();
html {
width: 100%;
height: 100%;
}
body {
width: 100%;
height: 100%;
font-family: 'Open Sans', sans-serif;
background: #333;
}
h1, h2, h3, h4, h5, h6 {
color: #000;
}
#main_stream {
padding-top: 90px;
}
.main-login{
background-color: #fff;
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
-moz-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
-webkit-box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
box-shadow: 0px 2px 2px rgba(0, 0, 0, 0.3);
}
.main-center{
margin-top: 30px;
margin: 0 auto;
padding: 40px 40px;
}
.comment-list .row {
margin-bottom: 0px;
}
.comment-list .panel .panel-heading {
padding: 4px 15px;
position: absolute;
border:none;
/*Panel-heading border radius*/
border-top-right-radius:0px;
top: 1px;
}
.comment-list .panel .panel-heading.right {
border-right-width: 0px;
/*Panel-heading border radius*/
border-top-left-radius:0px;
right: 16px;
}
.comment-list .panel .panel-heading .panel-body {
padding-top: 6px;
}
.comment-list figcaption {
/*For wrapping text in thumbnail*/
word-wrap: break-word;
}
/* Portrait tablets and medium desktops */
@media (min-width: 768px) {
.comment-list .arrow:after, .comment-list .arrow:before {
content: "";
position: absolute;
width: 0;
height: 0;
border-style: solid;
border-color: transparent;
}
.comment-list .panel.arrow.left:after, .comment-list .panel.arrow.left:before {
border-left: 0;
}
/*****Left Arrow*****/
/*Outline effect style*/
.comment-list .panel.arrow.left:before {
left: 0px;
top: 30px;
/*Use boarder color of panel*/
border-right-color: inherit;
border-width: 16px;
}
/*Background color effect*/
.comment-list .panel.arrow.left:after {
left: 1px;
top: 31px;
/*Change for different outline color*/
border-right-color: #FFFFFF;
border-width: 15px;
}
/*****Right Arrow*****/
/*Outline effect style*/
.comment-list .panel.arrow.right:before {
right: -16px;
top: 30px;
/*Use boarder color of panel*/
border-left-color: inherit;
border-width: 16px;
}
/*Background color effect*/
.comment-list .panel.arrow.right:after {
right: -14px;
top: 31px;
/*Change for different outline color*/
border-left-color: #FFFFFF;
border-width: 15px;
}
}
.comment-list .comment-post {
margin: 35px 15px 15px 35px;
}
package controllers
//
// GangGo Application Server
// 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 (
"github.com/revel/revel"
)
type App struct {
*revel.Controller
}
func (c App) Index() revel.Result {
return c.Render()
}
package controllers
//
// GangGo Application Server
// 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"
"github.com/ganggo/ganggo/app/models"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/postgres"
_ "github.com/jinzhu/gorm/dialects/mssql"
_ "github.com/jinzhu/gorm/dialects/mysql"
_ "github.com/jinzhu/gorm/dialects/sqlite"
)
type Hcard struct {
*revel.Controller
}
func (c Hcard) User() revel.Result {
var (
guid string
person models.Person
)
c.Params.Bind(&guid, "guid")
db, err := gorm.Open(models.DB.Driver, models.DB.Url)
if err != nil {
revel.WARN.Println(err)
return c.Render()
}
defer db.Close()
err = db.Where("guid = ?", guid).First(&person).Error
if err != nil {
c.Response.Status = http.StatusNotFound
revel.WARN.Println(err)
return c.Render()
}
var profile models.Profile
err = db.Where("person_id = ?", person.ID).First(&profile).Error
if err != nil {
c.Response.Status = http.StatusNotFound
revel.WARN.Println(err)
return c.Render()
}
revel.Config.SetSection("ganggo")
proto := revel.Config.StringDefault("proto", "http://")
address := revel.Config.StringDefault("address", "localhost")
c.RenderArgs["profile"] = profile
c.RenderArgs["person"] = person
c.RenderArgs["proto"] = proto
c.RenderArgs["address"] = address
return c.Render()
}
package controllers
//
// GangGo Application Server
// 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 (
"github.com/revel/revel"
"github.com/ganggo/ganggo/app/models"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/postgres"
_ "github.com/jinzhu/gorm/dialects/mssql"
_ "github.com/jinzhu/gorm/dialects/mysql"
_ "github.com/jinzhu/gorm/dialects/sqlite"
)
var _arrange bool
func init() {
revel.InterceptFunc(requiresLogin, revel.BEFORE, &Stream{})
revel.InterceptFunc(requiresLogin, revel.BEFORE, &Search{})
revel.InterceptFunc(requiresLogin, revel.BEFORE, &Profile{})
revel.TemplateFuncs["isLoggedIn"] = func(token interface {}) bool {
switch token.(type) {
case string:
return true
}
return false
}
revel.TemplateFuncs["person"] = func(id uint) (person models.Person) {
db, err := gorm.Open(models.DB.Driver, models.DB.Url)
if err != nil {
revel.ERROR.Println(err)
return
}
defer db.Close()
err = db.First(&person, id).Error
if err != nil {
revel.ERROR.Println(err, id)
return
}
err = db.Where("person_id = ?", person.ID).First(&person.Profile).Error
if err != nil {
revel.ERROR.Println(err, person)
return
}
return
}
revel.TemplateFuncs["swapElement"] = func() bool {
return _arrange
}
revel.TemplateFuncs["toggleSwapElement"] = func() bool {
if _arrange {
_arrange = false
} else {
_arrange = true
}
return _arrange
}
}
func requiresLogin(c *revel.Controller) revel.Result {
var session models.Session
db, err := gorm.Open(models.DB.Driver, models.DB.Url)
if err != nil {
revel.WARN.Println(err)
return c.Render()
}
defer db.Close()
err = db.Where("token = ?", c.Session["TOKEN"]).First(&session).Error
if err != nil {
c.Flash.Error("Please log in first")
return c.Redirect(App.Index)
}
c.RenderArgs["TOKEN"] = c.Session["TOKEN"]
return nil
}
package controllers
//
// GangGo Application Server
// 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 (
"github.com/revel/revel"
"github.com/ganggo/ganggo/app/models"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/postgres"
_ "github.com/jinzhu/gorm/dialects/mssql"
_ "github.com/jinzhu/gorm/dialects/mysql"
_ "github.com/jinzhu/gorm/dialects/sqlite"
)
type Profile struct {
*revel.Controller
}
func (p Profile) Index() revel.Result {
var (
guid string
person models.Person
)
p.Params.Bind(&guid, "guid")
db, err := gorm.Open(models.DB.Driver, models.DB.Url)
if err != nil {
revel.WARN.Println(err)
return p.Render()
}
defer db.Close()
err = db.Where("guid = ?", guid).First(&person).Error
if err != nil {
revel.WARN.Println(err)
return p.Redirect(Stream.Index)
}
err = db.Where("person_id = ?", person.ID).First(&person.Profile).Error
if err != nil {
revel.WARN.Println(err)
return p.Redirect(Stream.Index)
}
p.RenderArgs["person"] = person
return p.Render()
}
package controllers
//
// GangGo Application Server
// 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"
"github.com/ganggo/federation"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/postgres"
_ "github.com/jinzhu/gorm/dialects/mssql"
_ "github.com/jinzhu/gorm/dialects/mysql"
_ "github.com/jinzhu/gorm/dialects/sqlite"
"github.com/ganggo/ganggo/app/models"
"github.com/ganggo/ganggo/app/jobs"
)
type Receiver struct {
*revel.Controller
}
func (r Receiver) Public() revel.Result {
var xml string
db, err := gorm.Open(models.DB.Driver, models.DB.Url)
if err != nil {
revel.WARN.Println(err)
return r.Render()
}
defer db.Close()
r.Params.Bind(&xml, "xml")
r.Response.ContentType = "application/json"
request, err := federation.PreparePublicRequest(xml)
if err != nil {
r.Response.Status = http.StatusNotAcceptable
return r.Render()
}
// NOTE investigate whether this is a
// d* problem in production mode as well
go func() {
// check if author is already known
fetchAuthor := jobs.FetchAuthor{
Author: request.Header.AuthorId,
}
fetchAuthor.Run()
if fetchAuthor.Err != nil {
revel.ERROR.Println(err)
return
}
entity, err := request.Parse(
[]byte(fetchAuthor.Person.SerializedPublicKey))
if err != nil {
revel.ERROR.Println(err)
return
}
receiverJob := jobs.Receiver{
Entity: entity,
}
go receiverJob.Run()
}()
return r.Render()
}
func (r Receiver) Private() revel.Result {
var (
guid string
xml string
person models.Person
user models.User
)
db, err := gorm.Open(models.DB.Driver, models.DB.Url)
if err != nil {
revel.WARN.Println(err)
return r.Render()
}
defer db.Close()
r.Params.Bind(&xml, "xml")
r.Params.Bind(&guid, "guid")
r.Response.ContentType = "application/json"
err = db.Where("guid like ?", guid).First(&person).Error
if err != nil {
revel.ERROR.Println(err)
// diaspora will not process on StatusNotAcceptable
return r.Render()
}
err = db.First(&user, person.UserID).Error
if err != nil {
revel.ERROR.Println(err)
r.Response.Status = http.StatusNotAcceptable
return r.Render()
}
request, err := federation.PreparePrivateRequest(xml,
[]byte(user.SerializedPrivateKey))
if err != nil {
revel.ERROR.Println(err)
r.Response.Status = http.StatusNotAcceptable
return r.Render()
}
// NOTE investigate whether this is a
// d* problem in production mode as well
go func() {
// check if author is already known
fetchAuthor := jobs.FetchAuthor{