Skip to content

Commit

Permalink
🔥
Browse files Browse the repository at this point in the history
  • Loading branch information
Urban Ishimwe committed Apr 27, 2020
1 parent 2d8bfc2 commit 660965e
Show file tree
Hide file tree
Showing 22 changed files with 168 additions and 140 deletions.
3 changes: 2 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ PUBLIC_KEY=

# slack keys
SLACK_CLIENT_ID=
SLACK_CLIENT_SECRET=
SLACK_CLIENT_SECRET=
SLACK_SIGNING_SECRET=
6 changes: 0 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,4 @@ run:
start_db: #this may only work on UNIX
mongod --fork --logpath ~/mongod/mongod.log --dbpath ~/mongod

compile:
echo "Compiling for every OS and Platform"
GOOS=linux GOARCH=arm go build -o bin/linux/arm main.go
GOOS=linux GOARCH=arm64 go build -o bin/linux/arm64 main.go
GOOS=freebsd GOARCH=386 go build -o bin/freebsd/386 main.go

lint: vet fix fmt
3 changes: 2 additions & 1 deletion pkg/config/config.go → config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"os"

env "github.com/joho/godotenv"
"github.com/rwandaopensource/botx/pkg/helper"
"github.com/rwandaopensource/botx/helper"
)

// ErrEnv error returned when one the variables are missing
Expand Down Expand Up @@ -40,6 +40,7 @@ func Config(enforce bool) {
"SLACK_CLIENT_SECRET",
"PRIVATE_KEY",
"PUBLIC_KEY",
"SLACK_SIGNING_SECRET",
}
var missingEnv string
for _, key := range requiredEnv {
Expand Down
19 changes: 19 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package config_test

import (
"os"
"testing"

"github.com/rwandaopensource/botx/config"
"github.com/rwandaopensource/botx/helper"
)

func TestConfigParseError(t *testing.T) {
tmp := os.Getenv("PRIVATE_KEY")
os.Setenv("PRIVATE_KEY", "p")
config.Config(false)
if v := os.Getenv("PRIVATE_KEY"); v != "p" {
helper.TestError(t, "parsing config failed")
}
os.Setenv("PRIVATE_KEY", tmp)
}
48 changes: 48 additions & 0 deletions controller/controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package controller

import (
"errors"
"fmt"
"net/http"
"os"
"strings"
"time"

"github.com/rwandaopensource/botx/database"
"github.com/rwandaopensource/botx/helper"
"github.com/slack-go/slack"
)

var (
slackSigningSecret = os.Getenv("SLACK_SIGNING_SECRET")
slackClientID = os.Getenv("SLACK_CLIENT_ID")
slackClientSecret = os.Getenv("SLACK_CLIENT_SECRET")
slackError = "invalid_client_id,bad_client_secret,oauth_authorization_url_mismatch,bad_redirect_uri"
)

// Install http.handler for installer command
func Install(rw http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
code := r.URL.Query().Get("code")
e := r.URL.Query().Get("error")
if e != "" {
if strings.Contains(slackError, e) {
rw.WriteHeader(http.StatusInternalServerError)
helper.PrintError(errors.New(e), "during install")
return
}
rw.WriteHeader(http.StatusInternalServerError)
fmt.Fprint(rw, strings.Join(strings.Split(e, "_"), " "))
return
}
t, err := slack.GetOAuthResponse(http.DefaultClient, slackClientID, slackClientSecret, code, "")
if err != nil {
rw.WriteHeader(http.StatusNotAcceptable)
return
}
team := database.Workspace{*t, time.Now().Nanosecond(), time.Now().Nanosecond()}
err = database.CreateWorkspace(team)
if err != nil {
rw.WriteHeader(http.StatusInternalServerError)
}
}
23 changes: 16 additions & 7 deletions pkg/database/database.go → database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"os"
"time"

"github.com/rwandaopensource/botx/pkg/config"
"github.com/rwandaopensource/botx/pkg/helper"
"github.com/rwandaopensource/botx/config"
"github.com/rwandaopensource/botx/helper"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
Expand Down Expand Up @@ -35,7 +35,6 @@ func InitDB() {
opts.SetRetryReads(true)
opts.SetRetryWrites(true)
opts.SetSocketTimeout(time.Second * 5)
opts.SetMaxConnIdleTime(time.Second * 5)
if opts.Validate() != nil {
helper.FatalError(errDBOptions, "")
}
Expand All @@ -48,6 +47,9 @@ func InitDB() {
if DB = Client.Database(dbName); DB != nil {
helper.Verbose("db connected ✅")
}
// Initializing tables
UserModel = DB.Collection("users")
WorkspaceModel = DB.Collection("workspaces")
}

// Drop will drop all tables, better be done before running tests
Expand All @@ -72,14 +74,21 @@ func DropSome(t []string) error {
return nil
}

// CloseDB releases connection open by database
func CloseDB() {
// Close releases connection opened by database
func Close() {
err := Client.Disconnect(context.TODO())
helper.FatalError(err, "")
}

// Tables have all needed tables to run this app.
// Tables all tables name
var Tables []string = []string{"users"}

/**
the following section define all tables
**/

// UserModel represent users table
var UserModel = DB.Collection("users")
var UserModel *mongo.Collection

// WorkspaceModel reposents workspace table
var WorkspaceModel *mongo.Collection
19 changes: 9 additions & 10 deletions pkg/database/users.go → database/user.go
Original file line number Diff line number Diff line change
@@ -1,28 +1,27 @@
package database

import (
"context"
"errors"
"time"

"github.com/rwandaopensource/botx/pkg/helper"
"github.com/rwandaopensource/botx/helper"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)

// User represent a user
type User struct {
// ClientID is the id signed to the user
ClientID string
// ClientSecret is the secret signed to the user
ClientSecret string
// TeamID slack workspace id

CreatedAt time.Duration `json:"created_at"`
UpdatedAt time.Duration `json:"updated_at"`
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
TeamID string `json:"team_id"`
}

// ReadUser read a single user
func ReadUser(clientID string) (*User, error) {
ctx, cancel := helper.ReadRecordCtx()
defer cancel()
res := UserModel.FindOne(ctx, bson.M{"clientId": clientID}, nil)
res := UserModel.FindOne(context.TODO(), bson.M{"clientId": clientID}, nil)
err := res.Err()
if errors.Is(err, mongo.ErrNoDocuments) {
return nil, nil
Expand Down
23 changes: 23 additions & 0 deletions database/workspace.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package database

import (
"context"

"github.com/slack-go/slack"
)

// Workspace represent workspace
type Workspace struct {
slack.OAuthResponse
CreatedAt int `json:"created_at"`
UpdatedAt int `json:"updated_at"`
}

// CreateWorkspace store workspace details in the database
func CreateWorkspace(workspace Workspace) error {
_, err := WorkspaceModel.InsertOne(context.TODO(), workspace, nil)
if err != nil {
return err
}
return nil
}
23 changes: 23 additions & 0 deletions helper/html.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package helper

import (
"fmt"
"os"
)

// InstallHTML return html for installing app
func InstallHTML() string {
slackClientID := os.Getenv("SLACK_CLIENT_ID")
host := os.Getenv("REDIRECT_URI")
return fmt.Sprintf(`
<html lang="en">
<head>
<title> Install slack </tile>
</head>
<h1> Install this app in your slack workspace </h1>
<a href="https://slack.com/oauth/v2/authorize?client_id=%s&scope=im:write,chat:write,users:read,reactions:read,chat:write.public,incoming-webhook&redirect_uri=%s">
<img alt="Add to Slack" height="40" width="139" src="https://platform.slack-edge.com/img/add_to_slack.png" srcset="https://platform.slack-edge.com/img/add_to_slack.png 1x, https://platform.slack-edge.com/img/[email protected] 2x">
</a>
</html>
`, slackClientID, host)
}
File renamed without changes.
2 changes: 1 addition & 1 deletion pkg/helper/token_test.go → helper/token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"crypto/ed25519"
"testing"

"github.com/rwandaopensource/botx/pkg/helper"
"github.com/rwandaopensource/botx/helper"
)

func TestED25519PublicAndPrivate(t *testing.T) {
Expand Down
File renamed without changes.
20 changes: 12 additions & 8 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,31 @@ import (
"os/signal"
"time"

"github.com/rwandaopensource/botx/pkg/database"
"github.com/rwandaopensource/botx/pkg/helper"
"github.com/rwandaopensource/botx/pkg/route"
"github.com/rwandaopensource/botx/pkg/util"
"github.com/rwandaopensource/botx/database"
"github.com/rwandaopensource/botx/helper"
"github.com/rwandaopensource/botx/route"
"github.com/rwandaopensource/botx/util"
)

func main() {

defer database.CloseDB()
defer database.Close()
if util.Command() {
return
}

ADDR := os.Getenv("PORT")
if ADDR == "" {
ADDR = ":8080"
}
s := &http.Server{
Addr: route.ADDR,
Handler: route.Router(),
Addr: ADDR,
Handler: route.NewRouter(),
ReadTimeout: 20 * time.Second,
WriteTimeout: 20 * time.Second,
MaxHeaderBytes: 1 << 20,
}
helper.Print("starting server", route.ADDR)
helper.Print("starting server", ADDR)

go func() {
helper.FatalError(s.ListenAndServe(), "")
Expand Down
8 changes: 0 additions & 8 deletions pkg/controller/controller.go

This file was deleted.

16 changes: 0 additions & 16 deletions pkg/helper/ctx.go

This file was deleted.

17 changes: 0 additions & 17 deletions pkg/route/addr.go

This file was deleted.

11 changes: 0 additions & 11 deletions pkg/route/command.go

This file was deleted.

19 changes: 11 additions & 8 deletions pkg/route/route.go → route/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,37 @@ import (
"os"

"github.com/gorilla/mux"
"github.com/rwandaopensource/botx/controller"
)

// Router the
func Router() *mux.Router {
// NewRouter ...
func NewRouter() *mux.Router {
var origin = os.Getenv("ORIGIN")
if origin == "" {
origin = "*"
}

r := mux.NewRouter()
rt := mux.NewRouter()

// HOME ROUTE == PONG
r.HandleFunc("/", func(rw http.ResponseWriter, _ *http.Request) {
rt.HandleFunc("/", func(rw http.ResponseWriter, _ *http.Request) {
rw.Write([]byte("PONG"))
}).Methods(http.MethodGet, http.MethodPost)

// OPTIONS request
r.Methods(http.MethodOptions).HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
rt.Methods(http.MethodOptions).HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
rw.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE")
rw.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
rw.Header().Set("Access-Control-Allow-Origin", origin)
rw.Header().Set("Access-Control-Allow-Credentials", "true")
rw.WriteHeader(http.StatusNoContent)
})

r.HandleFunc("*", func(rw http.ResponseWriter, _ *http.Request) {
rt.HandleFunc("/install", controller.Install)

rt.HandleFunc("*", func(rw http.ResponseWriter, _ *http.Request) {
rw.WriteHeader(http.StatusNotFound)
}).Methods(http.MethodGet, http.MethodPost)
})

return r
return rt
}
Loading

0 comments on commit 660965e

Please sign in to comment.