Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

updates #1

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
31 changes: 3 additions & 28 deletions Gopkg.lock

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

40 changes: 34 additions & 6 deletions Gopkg.toml
@@ -1,11 +1,39 @@
[prune]
go-tests = true
unused-packages = true
# Gopkg.toml example
#
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
# for detailed Gopkg.toml documentation.
#
# required = ["github.com/user/thing/cmd/thing"]
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
#
# [[constraint]]
# name = "github.com/user/project"
# version = "1.0.0"
#
# [[constraint]]
# name = "github.com/user/project2"
# branch = "dev"
# source = "github.com/myfork/project2"
#
# [[override]]
# name = "github.com/x/y"
# version = "2.4.0"
#
# [prune]
# non-go = false
# go-tests = true
# unused-packages = true

[[constraint]]
name = "github.com/satori/go.uuid"
version = "1.2.0"
ignored = ["github.com/lheinrichde/golib/*"]

[[constraint]]
name = "github.com/lib/pq"
version = "1.0.0"

[[constraint]]
branch = "master"
name = "golang.org/x/crypto"

[prune]
go-tests = true
unused-packages = true
2 changes: 1 addition & 1 deletion README.md
@@ -1 +1 @@
# nerocp-backend
# evortexcp-backend
250 changes: 250 additions & 0 deletions cmd/evortexcp-backend/evortexcp-backend.go
@@ -0,0 +1,250 @@
package main

import (
"database/sql"
"errors"
"fmt"
"log"
"net"

"golang.org/x/crypto/bcrypt"

"github.com/lheinrichde/evortexcp-backend/internal/app/handlers"

"github.com/lheinrichde/golib/pkg/config"
"github.com/lheinrichde/golib/pkg/crypter"
"github.com/lheinrichde/golib/pkg/db"
"github.com/lheinrichde/golib/pkg/handler"
"github.com/lheinrichde/golib/pkg/module"
"github.com/lheinrichde/golib/pkg/setup"
)

// main function
func main() {
var err error

// config
err = config.LoadConfig("config.json")
if err != nil {
panic(err)
}

// log
if config.Get("app", "logType") == "file" {
err = setup.LogToFile(config.Get("app", "logFile"))
if err != nil {
panic(err)
}
}

// database
err = setupDB()
if err != nil {
panic(err)
}

// server
err = startServer()
if err != nil {
panic(err)
}
registerHandlers()

// started
fmt.Println("evortexcp-backend (c) 2018 Lennart Heinrich")

// modules
err = module.LoadModules(config.Get("app", "modules"))
if err != nil {
panic(err)
}

// keep open
<-make(chan bool)
}

// register known handlers
func registerHandlers() {
handler.Add("getperms", handlers.GetPerms)
handler.Add("getroleid", handlers.GetRoleID)
handler.Add("getrolename", handlers.GetRoleName)
handler.Add("getusers", handlers.GetUsers)
handler.Add("getroles", handlers.GetRoles)
handler.Add("createuser", handlers.CreateUser)
handler.Add("deleteuser", handlers.DeleteUser)
handler.Add("createrole", handlers.CreateRole)
handler.Add("deleterole", handlers.DeleteRole)
handler.Add("checkmodule", handlers.CheckModule)
handler.Add("deinstallmodule", handlers.DeinstallModule)
handler.Add("changepassword", handlers.ChangePassword)
}

// connect to and setup database
func setupDB() error {
var err error

// unused sql query values
var trash string

// connect to databse
db.Connect(config.Get("postgresql", "host"), config.Get("postgresql", "port"), config.Get("postgresql", "ssl"),
config.Get("postgresql", "database"), config.Get("postgresql", "username"), config.Get("postgresql", "password"))

// setup tables
_, err = db.DB.Exec(`-- Setup
-- Roles
CREATE TABLE IF NOT EXISTS roles (roleID SERIAL, roleName VARCHAR(255) UNIQUE,
PRIMARY KEY (roleID));

-- Permissions
CREATE TABLE IF NOT EXISTS permissions (role INT, permission VARCHAR(255),
FOREIGN KEY (role) REFERENCES roles (roleID) ON DELETE CASCADE);

-- Users
CREATE TABLE IF NOT EXISTS users (username VARCHAR(255) UNIQUE, passwordHash VARCHAR(255), role INT,
PRIMARY KEY(username), FOREIGN KEY (role) REFERENCES roles (roleID) ON DELETE CASCADE);`)
if err != nil {
return err
}

// check if a role exists
err = db.DB.QueryRow("SELECT roleID FROM roles;").Scan(&trash)
if err == sql.ErrNoRows {
// create default role
_, err = db.DB.Exec(`INSERT INTO roles (roleID, roleName) VALUES (1, 'admin');
INSERT INTO permissions (role, permission) VALUES (1, '*');`)
if err != nil {
return err
}
} else if err != nil {
// return error
return err
}

// check if a user exists
err = db.DB.QueryRow("SELECT username FROM users;").Scan(&trash)
if err == sql.ErrNoRows {
// generate bcrypt hash
passwordHashSHA3 := crypter.Hash("evortexcp_" + crypter.Hash("admin"))
var passwordHash []byte
passwordHash, err = bcrypt.GenerateFromPassword([]byte(passwordHashSHA3), bcrypt.DefaultCost+1)
if err != nil {
return err
}

// create default user
_, err = db.DB.Exec("INSERT INTO users (username, passwordHash, role) VALUES ('admin', $1, 1);", string(passwordHash))
if err != nil {
return err
}
} else if err != nil {
// return error
return err
}

return nil
}

// start listener
func startServer() error {
var err error

// listen to address
var listener net.Listener
listener, err = net.Listen("tcp", config.Get("server", "address"))
if err != nil {
return err
}

// async
go listen(listener)

return nil
}

// listener for incoming connections
func listen(listener net.Listener) {
var err error

// add default handler
handler.Add("default", handlers.Default)

for {
// accept connection
var conn net.Conn
conn, err = listener.Accept()
if err != nil {
log.Println(err)
}

// handle connection
go handleConnSafe(conn)
}
}

// handle connection and close
func handleConnSafe(conn net.Conn) {
var err error

err = handleConn(conn)
if err != nil {
handler.Write(conn, map[string]interface{}{"error": err.Error()})
}
conn.Close()
}

// handle connection
func handleConn(conn net.Conn) error {
var err error

// define variables
var request map[string]interface{}
request, err = handler.Read(conn)
if err != nil {
return err
}
typ, username, password := handler.GetString(request, "type"), handler.GetString(request, "username"), handler.GetString(request, "password")

// close connection if no type, username and password defined
if typ == "" {
return errors.New("404")
} else if username == "" || password == "" {
return errors.New("403")
}

// verify login
role := verifyLogin(username, password)
response := map[string]interface{}{}

// process verification
if role == nil {
// wrong login
return errors.New("403")
} else if typ == "login" {
// respond with role id
response["roleID"] = *role
handler.Write(conn, response)
return nil
}

// handle with handler
return handler.Get(typ)(conn, request, username)
}

// verify login
func verifyLogin(username, password string) *int {
var err error

// query database for user role
var passwordHash string
var role int
err = db.DB.QueryRow("SELECT passwordHash, role FROM users WHERE username = $1", username).Scan(&passwordHash, &role)

// not exists or wrong login data
if err == sql.ErrNoRows || bcrypt.CompareHashAndPassword([]byte(passwordHash), []byte(password)) != nil {
return nil
}

// return role
return &role
}