Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,7 @@
[[constraint]]
name = "github.com/gorilla/sessions"
version = "1.1.0"

[[constraint]]
name = "github.com/rs/cors"
version = "1.2.0"
11 changes: 6 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Package configuration
PROJECT = code-annotation
COMMANDS = server/cmd/code-annotation
COMMANDS = cli/server
DEPENDENCIES = github.com/golang/dep/cmd/dep

# Including ci Makefile
Expand All @@ -12,8 +12,9 @@ CI_FOLDER = .ci
YARN = yarn
REMOVE = rm -rf

SERVER_URL ?= /api
API_PORT ?= 8080
HOST ?= 127.0.0.1
PORT ?= 8080
SERVER_URL ?= //$(HOST):$(PORT)

$(MAKEFILE):
@git clone --quiet $(CI_REPOSITORY) $(CI_FOLDER); \
Expand Down Expand Up @@ -42,7 +43,7 @@ build: dependencies-frontend

## Compiles the dashboard assets, and serve the dashboard through its API
serve: build
go run server/cmd/code-annotation/*
go run cli/server/server.go

gorun:
go run server/cmd/code-annotation/*
go run cli/server/server.go
File renamed without changes.
45 changes: 45 additions & 0 deletions cli/server/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package main

import (
"fmt"
"net/http"

"github.com/kelseyhightower/envconfig"

"github.com/src-d/code-annotation/server"
"github.com/src-d/code-annotation/server/repository"
"github.com/src-d/code-annotation/server/service"
)

type appConfig struct {
Host string `envconfig:"HOST"`
Port int `envconfig:"PORT" default:"8080"`
UIDomain string `envconfig:"UI_DOMAIN" default:"http://127.0.0.1:8080"`
}

func main() {
// main configuration
var conf appConfig
envconfig.MustProcess("", &conf)

// create repos
userRepo := &repository.Users{}

// create services
var oauthConfig service.OAuthConfig
envconfig.MustProcess("oauth", &oauthConfig)
oauth := service.NewOAuth(oauthConfig.ClientID, oauthConfig.ClientSecret)

var jwtConfig service.JWTConfig
envconfig.MustProcess("jwt", &jwtConfig)
jwt := service.NewJWT(jwtConfig.SigningKey)

// loger
logger := service.NewLogger()

// start the router
router := server.Router(logger, jwt, oauth, conf.UIDomain, userRepo, "build")
logger.Info("running...")
err := http.ListenAndServe(fmt.Sprintf("%s:%d", conf.Host, conf.Port), router)
logger.Fatal(err)
}
82 changes: 0 additions & 82 deletions server/cmd/code-annotation/main.go

This file was deleted.

24 changes: 24 additions & 0 deletions server/handler/assignments.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package handler

import (
"net/http"

"github.com/src-d/code-annotation/server/serializer"
)

func GetAssignmentsForUserExperiment() RequestProcessFunc {
return func(r *http.Request) (*serializer.Response, error) {
return nil, serializer.NewHTTPError(http.StatusNotImplemented)
}
}

type assignmentRequest struct {
Answer string `json:"answer"`
Duration int `json:"duration"`
}

func SaveAssignment() RequestProcessFunc {
return func(r *http.Request) (*serializer.Response, error) {
return nil, serializer.NewHTTPError(http.StatusNotImplemented)
}
}
23 changes: 15 additions & 8 deletions server/handler/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/sirupsen/logrus"
"github.com/src-d/code-annotation/server/repository"
"github.com/src-d/code-annotation/server/serializer"
"github.com/src-d/code-annotation/server/service"
)

Expand All @@ -18,33 +19,39 @@ func Login(oAuth *service.OAuth) http.HandlerFunc {
}

// OAuthCallback makes exchange with oauth provider, gets&creates user and redirects to index page with JWT token
func OAuthCallback(oAuth *service.OAuth, jwt *service.JWT, userRepo *repository.Users, uiDomain string) http.HandlerFunc {
func OAuthCallback(
oAuth *service.OAuth,
jwt *service.JWT,
userRepo *repository.Users,
uiDomain string,
logger logrus.FieldLogger,
) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if err := oAuth.ValidateState(r, r.FormValue("state")); err != nil {
writeResponse(w, respErr(http.StatusBadRequest, err.Error()))
write(w, r, serializer.NewEmptyResponse(), serializer.NewHTTPError(http.StatusBadRequest))
return
}

code := r.FormValue("code")
user, err := oAuth.GetUser(r.Context(), code)
if err != nil {
logrus.Errorf("oauth get user error: %s", err)
logger.Errorf("oauth get user error: %s", err)
// FIXME can it be not server error? for wrong code
writeResponse(w, respInternalErr())
write(w, r, serializer.NewEmptyResponse(), err)
return
}

// FIXME with real repo we need to check does user exists already or not
if err := userRepo.Create(user); err != nil {
logrus.Errorf("can't create user: %s", err)
writeResponse(w, respInternalErr())
logger.Errorf("can't create user: %s", err)
write(w, r, serializer.NewEmptyResponse(), err)
return
}

token, err := jwt.MakeToken(user)
if err != nil {
logrus.Errorf("make jwt token error: %s", err)
writeResponse(w, respInternalErr())
logger.Errorf("make jwt token error: %s", err)
write(w, r, serializer.NewEmptyResponse(), err)
return
}
url := fmt.Sprintf("%s/?token=%s", uiDomain, token)
Expand Down
13 changes: 13 additions & 0 deletions server/handler/experiments.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package handler

import (
"net/http"

"github.com/src-d/code-annotation/server/serializer"
)

func GetExperimentDetails() RequestProcessFunc {
return func(r *http.Request) (*serializer.Response, error) {
return nil, serializer.NewHTTPError(http.StatusNotImplemented)
}
}
13 changes: 13 additions & 0 deletions server/handler/file_pairs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package handler

import (
"net/http"

"github.com/src-d/code-annotation/server/serializer"
)

func GetFilePairDetails() RequestProcessFunc {
return func(r *http.Request) (*serializer.Response, error) {
return nil, serializer.NewHTTPError(http.StatusNotImplemented)
}
}
76 changes: 45 additions & 31 deletions server/handler/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,49 +2,63 @@ package handler

import (
"encoding/json"
"fmt"
"net/http"

"github.com/src-d/code-annotation/server/serializer"
"github.com/src-d/code-annotation/server/service"
)

func respOK(d interface{}) response {
return response{
statusCode: http.StatusOK,
Data: d,
}
}
func Get(rp RequestProcessFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
response, err := rp(r)
if response == nil {
response = serializer.NewEmptyResponse()
}

func respErr(statusCode int, msg string) response {
return response{
statusCode: statusCode,
Errors: []errObj{errObj{Title: msg}},
write(w, r, response, err)
}
}

func respInternalErr() response {
return respErr(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
}

type errObj struct {
Title string `json:"title"`
}
// write is the responsible of writing the response with the data from the passed *serializer.Response and error
// If the passed error has StatusCode, the http.Response will be returned with the StatusCode of the passed error
// If the passed error has not StatusCode, the http.Response will be returned as a http.StatusInternalServerError
func write(w http.ResponseWriter, r *http.Request, response *serializer.Response, err error) {
var statusCode int

type response struct {
statusCode int
Data interface{} `json:"data,omitempty"`
Errors []errObj `json:"errors,omitempty"`
}
// TODO: There should be no ppl calling write from the outside
if response == nil {
response = serializer.NewEmptyResponse()
}

type renderFunc func(r *http.Request) response
if err == nil {
statusCode = http.StatusOK
} else if httpError, ok := err.(serializer.HTTPError); ok {
statusCode = httpError.StatusCode()
response.Status = statusCode
response.Errors = []serializer.HTTPError{httpError}
} else {
statusCode = http.StatusInternalServerError
response.Status = statusCode
response.Errors = []serializer.HTTPError{serializer.NewHTTPError(statusCode, err.Error())}
}

func render(fn renderFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
writeResponse(w, fn(r))
if statusCode >= http.StatusBadRequest {
service.NewLogger().Error(err.Error())
}
}

func writeResponse(w http.ResponseWriter, resp response) {
w.WriteHeader(resp.statusCode)
if err := json.NewEncoder(w).Encode(&resp); err != nil {
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
content, err := json.Marshal(response)
if err != nil {
err = fmt.Errorf("response could not be marshalled; %s", err.Error())
http.Error(w, err.Error(), http.StatusInternalServerError)
service.NewLogger().Error(err.Error())
return
}

w.Header().Add("content-type", "application/json")
w.WriteHeader(statusCode)
w.Write(content)
}

// RequestProcessFunc is the function that takes a http.Request, and returns a serializer.Response and an error
type RequestProcessFunc func(*http.Request) (*serializer.Response, error)
Loading