...
 
Commits (11)
FROM golang:alpine AS builder
LABEL authors="Christian Muehlhaeuser: muesli@gmail.com"
# Install git & make
# Git is required for fetching the dependencies
RUN apk update && \
apk add --no-cache git make ca-certificates && \
update-ca-certificates
# Set the working directory for the container
WORKDIR /go/sangha
# Build the binary
COPY . .
RUN go build
FROM alpine
RUN apk update && \
apk add --no-cache ca-certificates tzdata && \
update-ca-certificates
COPY --from=builder /go/sangha/sangha /go/bin/sangha
# Expose the application port
EXPOSE 9980
# create a volume for the configuration persistence
VOLUME /conf
# This form of ENTRYPOINT allows the sangha process to catch signals from the `docker stop` command
ENTRYPOINT /go/bin/sangha --config /conf/sangha.conf serve
......@@ -4,11 +4,17 @@ import (
"bufio"
"errors"
"fmt"
"math/big"
"os"
"strconv"
"strings"
"time"
"github.com/brianvoe/gofakeit"
"github.com/gosimple/slug"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"gitlab.techcultivation.org/sangha/sangha/config"
"gitlab.techcultivation.org/sangha/sangha/db"
)
......@@ -27,6 +33,14 @@ var (
return executeDatabaseInit()
},
}
databaseMockCmd = &cobra.Command{
Use: "mock",
Short: "generate mock-up data",
Long: `The mock command generates mock-up data in the database`,
RunE: func(cmd *cobra.Command, args []string) error {
return executeDatabaseMock()
},
}
databaseWipeCmd = &cobra.Command{
Use: "wipe",
Short: "wipe the database",
......@@ -39,6 +53,7 @@ var (
func init() {
databaseCmd.AddCommand(databaseInitCmd)
databaseCmd.AddCommand(databaseMockCmd)
databaseCmd.AddCommand(databaseWipeCmd)
RootCmd.AddCommand(databaseCmd)
}
......@@ -49,6 +64,74 @@ func executeDatabaseInit() error {
db.GetDatabase()
db.InitDatabase()
reader := bufio.NewReader(os.Stdin)
fmt.Print("New password for user admin: ")
password, _ := reader.ReadString('\n')
db.GetDatabase()
context := &db.APIContext{
Config: *config.Settings,
}
ctx := context.NewAPIContext().(*db.APIContext)
user := db.User{
Nickname: "admin",
Email: "admin@techcultivation.org",
About: "admin",
Address: []string{},
ZIP: "",
City: "",
Country: "",
}
err := user.Save(ctx)
if err != nil {
return err
}
err = user.UpdatePassword(ctx, strings.TrimSpace(password))
if err != nil {
return err
}
project := db.Project{
Slug: "cct",
Name: "CCT",
Summary: "Center for the Cultivation of Technology",
About: "",
Website: "https://techcultivation.org",
License: "AGPL",
Repository: "https://techcultivation.org",
Private: false,
PrivateBalance: true,
}
err = project.Save(ctx)
if err != nil {
return err
}
budget := db.Budget{
ProjectID: &project.ID,
ParentID: 0,
Name: project.Name,
Private: false,
PrivateBalance: true,
}
err = budget.Save(ctx)
if err != nil {
return err
}
dbudget := db.Budget{
ProjectID: &project.ID,
ParentID: 0,
Name: "Donation Cuts",
Private: false,
PrivateBalance: true,
}
err = dbudget.Save(ctx)
if err != nil {
return err
}
return nil
}
......@@ -68,3 +151,106 @@ func executeDatabaseWipe() error {
return nil
}
func executeDatabaseMock() error {
reader := bufio.NewReader(os.Stdin)
fmt.Print("Do you really want to write mock-up data to the database?\nEnter 'MOCKUP' to confirm: ")
text, _ := reader.ReadString('\n')
if strings.TrimSpace(text) != "MOCKUP" {
return errors.New("Generating mock-up data requires user confirmation")
}
log.Println("Generating mock-up data")
db.GetDatabase()
context := &db.APIContext{
Config: *config.Settings,
}
ctx := context.NewAPIContext().(*db.APIContext)
gofakeit.Seed(time.Now().UnixNano())
for i := 0; i < 10; i++ {
code, err := mockProject(ctx)
if err != nil {
return err
}
for i := 0; i < 24; i++ {
t, err := mockPayment(ctx, 2, i%3 == 0)
if err != nil {
return err
}
if i%2 == 0 {
t.Pending = false
t.Code = code
err = t.Update(ctx)
if err != nil {
return err
}
}
}
}
return nil
}
func mockPayment(ctx *db.APIContext, budget int64, negative bool) (db.Payment, error) {
valuei, _ := big.NewFloat(gofakeit.Price(1, 100) * 100.0).Int64()
if negative {
valuei *= -1
}
t := db.Payment{
BudgetID: budget,
CreatedAt: gofakeit.DateRange(time.Now().AddDate(-1, 0, 0), time.Now()),
Amount: valuei,
Currency: "EUR",
Purpose: gofakeit.Sentence(5),
RemoteAccount: strconv.FormatInt(int64(gofakeit.CreditCard().Number), 10),
RemoteBankID: strconv.FormatInt(int64(gofakeit.CreditCard().Number), 10),
RemoteName: gofakeit.Name(),
Source: "hbci",
}
return t, t.Save(ctx)
}
func mockProject(ctx *db.APIContext) (string, error) {
name := gofakeit.Company()
project := db.Project{
Slug: slug.Make(name),
Name: name,
Summary: gofakeit.HipsterSentence(10),
About: gofakeit.HipsterParagraph(2, 4, 20, "."),
Website: gofakeit.URL(),
License: "GPL",
Repository: gofakeit.URL(),
Private: false,
PrivateBalance: true,
}
err := project.Save(ctx)
if err != nil {
return "", err
}
budget := db.Budget{
ProjectID: &project.ID,
ParentID: 0,
Name: project.Name,
Private: false,
PrivateBalance: true,
}
err = budget.Save(ctx)
if err != nil {
return "", err
}
code, err := ctx.LoadCodeByBudgetUUID(budget.UUID)
fmt.Println("Generated code:", code.Code)
return code.Code, nil
}
......@@ -2,6 +2,7 @@ package db
import (
"errors"
"log"
"math/rand"
"strconv"
"time"
......@@ -161,8 +162,13 @@ func (budget *Budget) Delete(context *APIContext) error {
// Balance returns this budget's total balance
func (budget *Budget) Balance(context *APIContext) (int64, error) {
if !budget.HasAccess(context.Auth) {
log.Println("no access:", context.Auth.ID, budget.UserID)
return 0, errors.New("No such budget")
}
if !budget.HasTransactionAccess(context.Auth) {
log.Println("private balance:", context.Auth.ID, budget.UserID)
return 0, errors.New("No access to private balance")
}
var val int64
err := context.QueryRow("SELECT COALESCE(SUM(amount), 0) FROM transactions WHERE budget_id = $1", budget.ID).
......@@ -172,10 +178,15 @@ func (budget *Budget) Balance(context *APIContext) (int64, error) {
// BalanceStats returns this budget's total balance for the past months
func (budget *Budget) BalanceStats(context *APIContext) ([]int64, error) {
var val []int64
if !budget.HasAccess(context.Auth) {
return []int64{}, errors.New("No such budget")
}
if !budget.HasTransactionAccess(context.Auth) {
return []int64{}, errors.New("No access to private balance")
}
var val []int64
lom := time.Now().UTC()
b := int64(-1)
for b != 0 {
err := context.QueryRow("SELECT COALESCE(SUM(amount), 0) FROM transactions WHERE budget_id = $1 AND created_at <= $2", budget.ID, lom).
......@@ -196,6 +207,10 @@ func (budget *Budget) HasAccess(user *User) bool {
return !budget.Private || user.ID == 1 || (budget.UserID != nil && user.ID == *budget.UserID)
}
func (budget *Budget) HasTransactionAccess(user *User) bool {
return !budget.PrivateBalance || user.ID == 1 || (budget.UserID != nil && user.ID == *budget.UserID)
}
// SearchBudgets searches database for budgets
func (context *APIContext) SearchBudgets(term string) ([]Budget, error) {
budgets := []Budget{}
......
......@@ -68,7 +68,8 @@ func (context *APIContext) Authentication(request *restful.Request) (interface{}
}
func (context *APIContext) SetAuth(auth interface{}) {
context.Auth = auth.(*User)
u := auth.(User)
context.Auth = &u
}
// LogSummary logs out the current context stats
......
......@@ -65,6 +65,7 @@ func InitDatabase() {
name text PRIMARY KEY,
value text
)`,
`CREATE TABLE IF NOT EXISTS users
(
id bigserial PRIMARY KEY,
......@@ -83,6 +84,7 @@ func InitDatabase() {
CONSTRAINT uk_users_uuid UNIQUE (uuid),
CONSTRAINT uk_users_email UNIQUE (email)
)`,
`CREATE TABLE IF NOT EXISTS projects
(
id bigserial PRIMARY KEY,
......@@ -100,10 +102,13 @@ func InitDatabase() {
private_balance bool DEFAULT true,
processing_cut int DEFAULT 10,
activated bool DEFAULT false,
user_id int,
CONSTRAINT uk_projects_uuid UNIQUE (uuid),
CONSTRAINT uk_projects_slug UNIQUE (slug),
CONSTRAINT uk_projects_repository UNIQUE (repository)
CONSTRAINT uk_projects_repository UNIQUE (repository),
CONSTRAINT fk_projects_user_id FOREIGN KEY (user_id) REFERENCES users (id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE
)`,
`CREATE TABLE IF NOT EXISTS budgets
(
id bigserial PRIMARY KEY,
......@@ -137,6 +142,7 @@ func InitDatabase() {
pending bool DEFAULT true,
CONSTRAINT fk_payments_budget_id FOREIGN KEY (budget_id) REFERENCES budgets (id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE RESTRICT
)`,
`CREATE TABLE IF NOT EXISTS transactions
(
id bigserial PRIMARY KEY,
......@@ -152,6 +158,7 @@ func InitDatabase() {
CONSTRAINT fk_transactions_to_budget_id FOREIGN KEY (to_budget_id) REFERENCES budgets (id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE RESTRICT,
CONSTRAINT fk_transactions_payment_id FOREIGN KEY (payment_id) REFERENCES payments (id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE RESTRICT
)`,
`CREATE TABLE IF NOT EXISTS codes
(
id bigserial PRIMARY KEY,
......@@ -163,6 +170,7 @@ func InitDatabase() {
CONSTRAINT uk_codes_budget_ids UNIQUE (budget_ids, ratios, user_id),
CONSTRAINT fk_codes_user_id FOREIGN KEY (user_id) REFERENCES users (id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE
)`,
`CREATE TABLE IF NOT EXISTS contributors
(
id bigserial PRIMARY KEY,
......
package db
import (
"errors"
"time"
)
......@@ -21,6 +22,7 @@ type Project struct {
PrivateBalance bool
ProcessingCut int64
Activated bool
UserID *int64
}
// LoadProjectByUUID loads a project by UUID from the database
......@@ -30,8 +32,12 @@ func (context *APIContext) LoadProjectByUUID(uuid string) (Project, error) {
return project, ErrInvalidID
}
err := context.QueryRow("SELECT id, uuid, slug, name, summary, about, website, license, repository, logo, created_at, private, private_balance, processing_cut, activated FROM projects WHERE uuid = $1", uuid).
Scan(&project.ID, &project.UUID, &project.Slug, &project.Name, &project.Summary, &project.About, &project.Website, &project.License, &project.Repository, &project.Logo, &project.CreatedAt, &project.Private, &project.PrivateBalance, &project.ProcessingCut, &project.Activated)
err := context.QueryRow("SELECT id, uuid, slug, name, summary, about, website, license, repository, logo, created_at, private, private_balance, processing_cut, activated, user_id FROM projects WHERE uuid = $1", uuid).
Scan(&project.ID, &project.UUID, &project.Slug, &project.Name, &project.Summary, &project.About, &project.Website, &project.License, &project.Repository, &project.Logo, &project.CreatedAt, &project.Private, &project.PrivateBalance, &project.ProcessingCut, &project.Activated, &project.UserID)
if !project.HasAccess(context.Auth) {
return Project{}, errors.New("No such project")
}
return project, err
}
......@@ -42,8 +48,12 @@ func (context *APIContext) GetProjectByID(id int64) (Project, error) {
return project, ErrInvalidID
}
err := context.QueryRow("SELECT id, uuid, slug, name, summary, about, website, license, repository, logo, created_at, private, private_balance, processing_cut, activated FROM projects WHERE id = $1", id).
Scan(&project.ID, &project.UUID, &project.Slug, &project.Name, &project.Summary, &project.About, &project.Website, &project.License, &project.Repository, &project.Logo, &project.CreatedAt, &project.Private, &project.PrivateBalance, &project.ProcessingCut, &project.Activated)
err := context.QueryRow("SELECT id, uuid, slug, name, summary, about, website, license, repository, logo, created_at, private, private_balance, processing_cut, activated, user_id FROM projects WHERE id = $1", id).
Scan(&project.ID, &project.UUID, &project.Slug, &project.Name, &project.Summary, &project.About, &project.Website, &project.License, &project.Repository, &project.Logo, &project.CreatedAt, &project.Private, &project.PrivateBalance, &project.ProcessingCut, &project.Activated, &project.UserID)
if !project.HasAccess(context.Auth) {
return Project{}, errors.New("No such project")
}
return project, err
}
......@@ -56,6 +66,10 @@ func (context *APIContext) GetProjectByUUID(uuid string) (Project, error) {
}
project = *projectsCache.Data().(*Project)
if !project.HasAccess(context.Auth) {
return Project{}, errors.New("No such project")
}
return project, nil
}
......@@ -66,8 +80,12 @@ func (context *APIContext) LoadProjectBySlug(slug string) (Project, error) {
return project, ErrInvalidID
}
err := context.QueryRow("SELECT id, uuid, slug, name, summary, about, website, license, repository, logo, created_at, private, private_balance, processing_cut, activated FROM projects WHERE slug = $1", slug).
Scan(&project.ID, &project.UUID, &project.Slug, &project.Name, &project.Summary, &project.About, &project.Website, &project.License, &project.Repository, &project.Logo, &project.CreatedAt, &project.Private, &project.PrivateBalance, &project.ProcessingCut, &project.Activated)
err := context.QueryRow("SELECT id, uuid, slug, name, summary, about, website, license, repository, logo, created_at, private, private_balance, processing_cut, activated, user_id FROM projects WHERE slug = $1", slug).
Scan(&project.ID, &project.UUID, &project.Slug, &project.Name, &project.Summary, &project.About, &project.Website, &project.License, &project.Repository, &project.Logo, &project.CreatedAt, &project.Private, &project.PrivateBalance, &project.ProcessingCut, &project.Activated, &project.UserID)
if !project.HasAccess(context.Auth) {
return Project{}, errors.New("No such project")
}
return project, err
}
......@@ -75,7 +93,7 @@ func (context *APIContext) LoadProjectBySlug(slug string) (Project, error) {
func (context *APIContext) LoadAllProjects() ([]Project, error) {
projects := []Project{}
rows, err := context.Query("SELECT id, uuid, slug, name, summary, about, website, license, repository, logo, created_at, private, private_balance, processing_cut, activated FROM projects")
rows, err := context.Query("SELECT id, uuid, slug, name, summary, about, website, license, repository, logo, created_at, private, private_balance, processing_cut, activated, user_id FROM projects")
if err != nil {
return projects, err
}
......@@ -83,11 +101,14 @@ func (context *APIContext) LoadAllProjects() ([]Project, error) {
defer rows.Close()
for rows.Next() {
project := Project{}
err = rows.Scan(&project.ID, &project.UUID, &project.Slug, &project.Name, &project.Summary, &project.About, &project.Website, &project.License, &project.Repository, &project.Logo, &project.CreatedAt, &project.Private, &project.PrivateBalance, &project.ProcessingCut, &project.Activated)
err = rows.Scan(&project.ID, &project.UUID, &project.Slug, &project.Name, &project.Summary, &project.About, &project.Website, &project.License, &project.Repository, &project.Logo, &project.CreatedAt, &project.Private, &project.PrivateBalance, &project.ProcessingCut, &project.Activated, &project.UserID)
if err != nil {
return projects, err
}
if !project.HasAccess(context.Auth) {
continue
}
projects = append(projects, project)
}
......@@ -188,6 +209,14 @@ func (project *Project) BalanceStats(context *APIContext) ([]int64, error) {
return b, nil
}
func (project *Project) HasAccess(user *User) bool {
return !project.Private || user.ID == 1 || (project.UserID != nil && user.ID == *project.UserID)
}
func (project *Project) HasTransactionAccess(user *User) bool {
return !project.PrivateBalance || user.ID == 1 || (project.UserID != nil && user.ID == *project.UserID)
}
// SearchProjects searches database for projects
func (context *APIContext) SearchProjects(term string) ([]Project, error) {
projects := []Project{}
......
package db
import (
"errors"
"time"
)
......@@ -45,6 +46,10 @@ func (project *Project) LoadTransactions(context *APIContext) ([]Transaction, er
return []Transaction{}, err
}
if !b.HasTransactionAccess(context.Auth) {
return []Transaction{}, errors.New("No such project")
}
return b.LoadTransactions(context)
/* transactions := []Transaction{}
......@@ -74,6 +79,10 @@ func (project *Project) LoadTransactions(context *APIContext) ([]Transaction, er
// LoadTransactions loads all transactions for a budget
func (budget *Budget) LoadTransactions(context *APIContext) ([]Transaction, error) {
if !budget.HasTransactionAccess(context.Auth) {
return []Transaction{}, errors.New("No such budget")
}
transactions := []Transaction{}
rows, err := context.Query("SELECT id, budget_id, from_budget_id, to_budget_id, amount, created_at, purpose, payment_id "+
......
module gitlab.techcultivation.org/sangha/sangha
go 1.12
require (
cloud.google.com/go v0.43.0 // indirect
github.com/Rhymond/go-money v0.4.0
github.com/badoux/checkmail v0.0.0-20181210160741-9661bd69e9ad
github.com/brianvoe/gofakeit v3.18.0+incompatible
github.com/coreos/bbolt v1.3.3 // indirect
github.com/coreos/etcd v3.3.13+incompatible // indirect
github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect
github.com/emicklei/go-restful v2.9.6+incompatible
github.com/emicklei/go-restful-swagger12 v0.0.0-20170926063155-7524189396c6
github.com/go-kit/kit v0.9.0 // indirect
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6 // indirect
github.com/google/pprof v0.0.0-20190723021845-34ac40c74b70 // indirect
github.com/gosimple/slug v1.6.0
github.com/grpc-ecosystem/grpc-gateway v1.9.5 // indirect
github.com/hashicorp/golang-lru v0.5.3 // indirect
github.com/json-iterator/go v1.1.7 // indirect
github.com/kisielk/errcheck v1.2.0 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
github.com/kr/pty v1.1.8 // indirect
github.com/lib/pq v1.2.0
github.com/magiconair/properties v1.8.1 // indirect
github.com/muesli/cache2go v0.0.0-20190609140403-5eb79359852d
github.com/muesli/smolder v0.0.0-20190730123621-c593c1532763
github.com/muesli/toktok v0.0.0-20181030220647-94235782aeac
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect
github.com/pelletier/go-toml v1.4.0 // indirect
github.com/pkg/errors v0.8.1 // indirect
github.com/prometheus/common v0.6.0 // indirect
github.com/prometheus/procfs v0.0.3 // indirect
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be // indirect
github.com/rogpeppe/fastuuid v1.2.0 // indirect
github.com/russross/blackfriday v2.0.0+incompatible // indirect
github.com/satori/go.uuid v1.2.0
github.com/sirupsen/logrus v1.4.2
github.com/spf13/afero v1.2.2 // indirect
github.com/spf13/cobra v0.0.5
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/viper v1.4.0 // indirect
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94 // indirect
github.com/stretchr/objx v0.2.0 // indirect
github.com/ugorji/go v1.1.7 // indirect
github.com/xrash/smetrics v0.0.0-20170218160415-a3153f7040e9 // indirect
gitlab.techcultivation.org/sangha/mq v0.0.0-20181128100227-b69bcf6541df
go.etcd.io/bbolt v1.3.3 // indirect
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
golang.org/x/exp v0.0.0-20190718202018-cfdd5522f6f6 // indirect
golang.org/x/image v0.0.0-20190729225735-1bd0cf576493 // indirect
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028 // indirect
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 // indirect
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e // indirect
golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a // indirect
google.golang.org/grpc v1.22.1 // indirect
honnef.co/go/tools v0.0.1-2019.2.2 // indirect
)
This diff is collapsed.
package statistics
import (
"net/http"
"gitlab.techcultivation.org/sangha/sangha/db"
"github.com/emicklei/go-restful"
......@@ -35,15 +33,6 @@ func (r *StatisticsResource) GetParams() []*restful.Parameter {
// Get sends out items matching the query parameters
func (r *StatisticsResource) Get(context smolder.APIContext, request *restful.Request, response *restful.Response, params map[string][]string) {
auth, err := context.Authentication(request)
if err != nil || auth.(db.User).ID != 1 {
smolder.ErrorResponseHandler(request, response, err, smolder.NewErrorResponse(
http.StatusUnauthorized,
"Admin permission required for this operation",
"StatisticsResource GET"))
return
}
resp := StatisticsResponse{}
resp.Init(context)
......
......@@ -45,22 +45,28 @@ func (r *TransactionResource) GetParams() []*restful.Parameter {
// GetByIDs sends out all items matching a set of IDs
func (r *TransactionResource) GetByIDs(context smolder.APIContext, request *restful.Request, response *restful.Response, ids []string) {
auth, err := context.Authentication(request)
if err != nil || auth.(db.User).ID != 1 {
smolder.ErrorResponseHandler(request, response, err, smolder.NewErrorResponse(
http.StatusUnauthorized,
"Admin permission required for this operation",
"TransactionResource GET"))
return
}
resp := TransactionResponse{}
resp.Init(context)
ctx := context.(*db.APIContext)
for _, id := range ids {
iid, _ := strconv.ParseInt(id, 10, 0)
transaction, err := context.(*db.APIContext).LoadTransactionByID(iid)
transaction, err := ctx.LoadTransactionByID(iid)
if err != nil {
r.NotFound(request, response)
return
}
budget, err := ctx.LoadBudgetByID(transaction.BudgetID)
if err != nil {
smolder.ErrorResponseHandler(request, response, err, smolder.NewErrorResponse(
http.StatusInternalServerError,
"Can't load budget",
"TransactionsResource GET"))
return
}
if !budget.HasTransactionAccess(ctx.Auth) {
r.NotFound(request, response)
return
}
......@@ -73,15 +79,6 @@ func (r *TransactionResource) GetByIDs(context smolder.APIContext, request *rest
// Get sends out items matching the query parameters
func (r *TransactionResource) Get(context smolder.APIContext, request *restful.Request, response *restful.Response, params map[string][]string) {
auth, err := context.Authentication(request)
if err != nil || auth.(db.User).ID != 1 {
smolder.ErrorResponseHandler(request, response, err, smolder.NewErrorResponse(
http.StatusUnauthorized,
"Admin permission required for this operation",
"TransactionResource GET"))
return
}
ctx := context.(*db.APIContext)
resp := TransactionResponse{}
resp.Init(context)
......@@ -90,7 +87,7 @@ func (r *TransactionResource) Get(context smolder.APIContext, request *restful.R
if len(params["project"]) > 0 {
var project db.Project
project, err = context.(*db.APIContext).LoadProjectByUUID(params["project"][0])
project, err := ctx.LoadProjectByUUID(params["project"][0])
if err != nil {
r.NotFound(request, response)
return
......@@ -106,7 +103,7 @@ func (r *TransactionResource) Get(context smolder.APIContext, request *restful.R
}
} else if len(params["budget"]) > 0 {
var budget db.Budget
budget, err = ctx.LoadBudgetByUUID(params["budget"][0])
budget, err := ctx.LoadBudgetByUUID(params["budget"][0])
if err != nil {
r.NotFound(request, response)
return
......@@ -129,7 +126,7 @@ func (r *TransactionResource) Get(context smolder.APIContext, request *restful.R
from, _ = time.Parse(timeLayout, params["from_date"][0])
}
if len(params["to_date"]) > 0 {
to, err = time.Parse(timeLayout, params["to_date"][0])
to, err := time.Parse(timeLayout, params["to_date"][0])
if err == nil {
to = to.Add(time.Hour * 24)
}
......
......@@ -60,7 +60,10 @@ func prepareTransactionResponse(context smolder.APIContext, transaction db.Trans
Amount: transaction.Amount,
CreatedAt: transaction.CreatedAt,
Purpose: transaction.Purpose,
PaymentID: transaction.PaymentID,
}
if ctx.Auth != nil && ctx.Auth.ID == 1 {
resp.PaymentID = transaction.PaymentID
}
budget, _ := ctx.LoadBudgetByID(transaction.BudgetID)
......