Skip to content

Commit

Permalink
Add api key to server
Browse files Browse the repository at this point in the history
  • Loading branch information
ashk123 committed Feb 5, 2024
1 parent 8f51f9f commit a66f5e2
Show file tree
Hide file tree
Showing 19 changed files with 238 additions and 21 deletions.
25 changes: 25 additions & 0 deletions Config/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
### How to use this folder

Welcome to the config folder, in this folder you can config your chat server with the Config cmds.

Be notice that the main Config file for your server is .env file you can find a sample .env file in the root of this project

For Create your configuration file, just make a `config.json` file here

### CMDS (JSON)

_ServerName -> information: your server name <br/>
Server_Description -> information: your server description<br/>
Server_Owner -> information: your server manager <br/>
Server_Date_Format -> Full Date format or simple Date Format_

### Example

```json
{
"Server_Name": "Sunsend1",
"Server_Description": "This is the Default Server",
"Server_Owner": "SunSend",
"Sever_Date_Format": "full" // full/normal/simple
}
```
1 change: 1 addition & 0 deletions Config/words.l
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nice
10 changes: 9 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
setup:
go run cmd/gen_key.go

run:
go run cmd/api/main.go

Expand All @@ -7,4 +10,9 @@ build:
doc:
touch doc
echo "welcome" > doc
echo "Done."
echo "Done."

config:
mkdir -p Config/
touch Config/config.json
echo "Done.""
Binary file removed Storage/SunSend.db
Binary file not shown.
5 changes: 5 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,8 @@
- [ ] Convert Error Numbers to a model
- [x] Add Create Channel
- [x] Add Database to save messages
- [ ] Add Server Route for more information about server
- [ ] Add managment panel for config server
- [ ] User Scripts for making small plugins to expand the server capability
- [ ] Add API key feature for servers
- [ ] Make a ConfigCore to manage config files
12 changes: 5 additions & 7 deletions cmd/api/main.go
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
package main

import (
"fmt"
"log"
"os"
"sunsend/internals/CoreConfig"
"sunsend/internals/DB"
"sunsend/internals/Handlers"
"sunsend/internals/Renderer"
"text/template"

"github.com/joho/godotenv"
"github.com/labstack/echo/v4"
)

func main() {
e := echo.New()
err := godotenv.Load(".env")
if err != nil {
log.Fatal(err.Error())
}
CoreConfig.UpdateConfigs() // load bouth .env configs and user configs
log.Println("Your API Key is: " + fmt.Sprintf("%s", CoreConfig.Configs.Server.Key))
// e.Use(middleware.Logger())
// e.Use(middleware.Recover())
e.Renderer = &Renderer.Template{
Expand All @@ -26,5 +24,5 @@ func main() {
Handlers.Handler(e)
DB.PrepairDBSystem()

e.Logger.Fatal(e.Start(":" + os.Getenv("PORT")))
e.Logger.Fatal(e.Start(":" + CoreConfig.Configs.Dotenv["PORT"]))
}
18 changes: 18 additions & 0 deletions cmd/gen_key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package main

import (
"crypto/sha256"
"fmt"

"github.com/thanhpk/randstr"
)

func GenerateAPIKey() [32]byte {
token := randstr.Hex(16) // generate 128-bit hex string
return sha256.Sum256([]byte(token))
}

func main() {
res := GenerateAPIKey()
fmt.Println("Your API KEY is: ", fmt.Sprintf("%X", res))
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/thanhpk/randstr v1.0.6 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
golang.org/x/crypto v0.17.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/thanhpk/randstr v1.0.6 h1:psAOktJFD4vV9NEVb3qkhRSMvYh4ORRaj1+w/hn4B+o=
github.com/thanhpk/randstr v1.0.6/go.mod h1:M/H2P1eNLZzlDwAzpkkkUvoyNNMbzRGhESZuEQk3r0U=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
Expand Down
File renamed without changes.
12 changes: 9 additions & 3 deletions internals/Base/Messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,25 @@ package Base
import (
"fmt"
"log"
"strings"
"sunsend/internals/DB"
"sunsend/internals/Data"
)

func IsEqulTo(message string) bool {
return message == "321"
for _, v := range *Data.LoadedWordList {
if message == v || strings.Contains(message, v) {
return true
}
}
return false
}

func CheckMessage(message string) int {
if len(message) > 30 {
return 15
return 15 // response 15 -> length error
} else if IsEqulTo(message) {
return 12
return 12 // response 12 -> Word error
}
return 0
}
Expand Down
40 changes: 40 additions & 0 deletions internals/Base/key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package Base

import (
"crypto/sha256"
"crypto/subtle"
"fmt"
"strings"
"sunsend/internals/CoreConfig"
)

// Doc: https://dev.to/caiorcferreira/implementing-a-safe-and-sound-api-key-authorization-middleware-in-go-3g2c

func GenerateAPIKey(rawkey string) [32]byte {
// token := randstr.Hex(16) // generate 128-bit hex string
return sha256.Sum256([]byte(rawkey))
}

func BearerToken(headers map[string][]string) (string, int) {
fmt.Println(headers)
api_key_org, ok := headers["Api_key"]
if !ok {
return "", 17 // invalid API KE Y
}
if len(strings.SplitN(api_key_org[0], " ", 2)) > 2 {
return "", 17
}
return strings.TrimSpace(api_key_org[0]), 0

}

// apiKeyIsValid checks if the given API key is valid and returns the principal if it is.
func ApiKeyIsValid(user_api_key string) int {
// hash := sha256.Sum256([]byte(user_api_key))
// key := hash[:]
if subtle.ConstantTimeCompare([]byte(CoreConfig.Configs.Server.Key), []byte(user_api_key)) == 1 {
return 0
}

return 17
}
48 changes: 48 additions & 0 deletions internals/CoreConfig/ConfigReader.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package CoreConfig

import (
"errors"
"log"
"os"
"sunsend/internals/Data"

"github.com/joho/godotenv"
)

var Configs *Data.Config
var rawapikey string

func getEnvConfig() (map[string]string, error) {
err := godotenv.Load(".env")
if err != nil {
// log.Fatal(err.Error())
return nil, errors.New("invalid or can't read .env file")
}
// It can be better to list of all the needed Config and iterate thought them
ret_values := make(map[string]string)
ret_values["PORT"] = os.Getenv("PORT")
ret_values["KEY"] = os.Getenv("KEY")
// copy(rawapikey[:], ret_values["KEY"]) // fix fixing some invalid memory address - TODO: Fix in better way - nice
rawapikey = ret_values["KEY"]
return ret_values, nil
}

func UpdateConfigs() {
envconfigs, err := getEnvConfig()
if err != nil {
log.Fatal(err.Error())
}
// TODO: get the user configs here

Configs = &Data.Config{
Dotenv: envconfigs,
Uconfig: nil, // for now just a little cute nil ^^
Server: &Data.Server{ // TODO: will holds data from user config file
Name: "test",
Description: "test1",
Owner: "test",
Date: "test",
Key: rawapikey,
},
}
}
9 changes: 7 additions & 2 deletions internals/DB/db_structure.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func createBaseTable() int {
db_work := getbasedb()

base_channels_table := `CREATE TABLE Channels (
"ID" integer NOT NULL PRIMARY KEY,
"ID" integer NOT NULL PRIMARY KEY,
"Name" TEXT,
"Description" TEXT,
"Owner" TEXT
Expand All @@ -31,7 +31,12 @@ func createBaseTable() int {
fmt.Println("this is where I stoped the program hahahahaha")
log.Fatalln(err.Error())
}
statement_channel.Exec() // Execute SQL Statements
res, err := statement_channel.Exec() // Execute SQL Statements
if err != nil {
// fmt.Println(err.Error(), res)
log.Fatal(err.Error(), res)
}

log.Println("Base Channels table created")
// CreateMessageTable()

Expand Down
2 changes: 2 additions & 0 deletions internals/Data/Response.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ func GetErrorByResult(res_code int) (string, int, string) {
return "Your Messages Length is more than 30 character", http.StatusBadRequest, "FAILD" // response Status Error - message length
case 16:
return "There is a problem in the system", http.StatusServiceUnavailable, "FAILD" // response Status Error - Server has problem (bug)
case 17:
return "Invalid API KEY", http.StatusBadRequest, "FAILD" // response Status Error - invalid api key
default:
return "There is a problem", http.StatusNotAcceptable, "FAILD" // Response Status Error - uknown Eror
}
Expand Down
7 changes: 7 additions & 0 deletions internals/Data/config_struct.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package Data

type Config struct {
Dotenv map[string]string // .env file configs
Uconfig map[string]string // usr `Config` folder configs
Server *Server
}
9 changes: 9 additions & 0 deletions internals/Data/server_struct.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package Data

type Server struct {
Name string
Description string
Owner string
Date string
Key string
}
25 changes: 25 additions & 0 deletions internals/Data/words.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package Data

/*
This file will holds the words that shouldn't be on chat or send as a data to the server
It is better to not change edit this file and instead make a words list on config/words.l
There words are default for each server, and you should not remove these.
*/

var LoadedWordList *[]string

var defaultWords []string = []string{
"321",
"nice",
"yes",
}

func LoadWordsFromConfig() {
// Load Words From Config File
LoadedWordList = &[]string{"config"}
*LoadedWordList = append(*LoadedWordList, defaultWords...)
}

func GetAllWords() *[]string {
return LoadedWordList
}
33 changes: 25 additions & 8 deletions internals/Routes/chat.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,31 @@ func GetChatPostAction(c echo.Context) error {
err := Base.CheckMessage(msg)
if err != 0 {
response, _ := Data.NewResponse(c, err, channel_id_user, nil)
return c.JSON(http.StatusBadRequest, response) // should be same Statuscode as NewResponse
_, error_code_org, _ := Data.GetErrorByResult(err)
return c.JSON(error_code_org, response) // should be same Statuscode as NewResponse
}
res_exists_channel := Base.ChannelExists(channel_id_user)
if res_exists_channel != 0 {
response_org, _ := Data.NewResponse(c, res_exists_channel, channel_id_user, nil)
return c.JSON(http.StatusBadRequest, response_org) // should be same Statuscode as NewResponse
_, error_code_org2, _ := Data.GetErrorByResult(res_exists_channel)
return c.JSON(error_code_org2, response_org) // should be same Statuscode as NewResponse
}

// fmt.Println(msg)
IChannel_id_ser, _ := strconv.Atoi(channel_id_user)
res := DB.InsertMsg(IChannel_id_ser, rand.Intn(999), user, msg, time.Now().String(), 0)
if res != 0 {
response, _ := Data.NewResponse(c, res, channel_id_user, nil)
return c.JSON(http.StatusBadRequest, response)
_, error_code_org3, _ := Data.GetErrorByResult(res_exists_channel)
return c.JSON(error_code_org3, response)
}
response, _ := Data.NewResponse(c, 0, channel_id_user, msg)
return c.JSON(http.StatusOK, response)
_, error_code_org4, _ := Data.GetErrorByResult(res_exists_channel)
return c.JSON(error_code_org4, response)

}

func StreamResponseJSON(c echo.Context, chat_data []*Data.Chat) error {
func StreamResponseJSON(c echo.Context, chat_data *Data.Response) error {
c.Response().Header().Set(echo.HeaderContentType, echo.MIMEApplicationJSONCharsetUTF8)
c.Response().WriteHeader(http.StatusOK)
return json.NewEncoder(c.Response()).Encode(chat_data)
Expand Down Expand Up @@ -70,10 +74,23 @@ func chatActionFunc(c echo.Context) error {
}

fmt.Println(len(chat_collection))

// response, _ = Data.NewResponse(c, res, channel_id, chat_collection)
headers := c.Request().Header
apiKey, res_api_key := Base.BearerToken(headers)
if res != 0 {
response, _ = Data.NewResponse(c, res_api_key, channel_id, nil)
_, error_code_org, _ := Data.GetErrorByResult(res_api_key)
return c.JSON(error_code_org, response)
}
res_check_api := Base.ApiKeyIsValid(apiKey)
if res_check_api != 0 {
response, _ = Data.NewResponse(c, res_check_api, channel_id, nil)
_, error_code_org, _ := Data.GetErrorByResult(res_check_api)
return c.JSON(error_code_org, response)
}
fmt.Println("API KEY:", apiKey, "requested to server succsessfully")
response, _ = Data.NewResponse(c, res, channel_id, chat_collection)
// return c.JSON(http.StatusOK, response)
return StreamResponseJSON(c, chat_collection) // Stream JSON File
return StreamResponseJSON(c, response) // Stream JSON File
// return c.JSON(http.StatusAccepted, map[string]interface{}{
// "asd": "nice",
// })
Expand Down

0 comments on commit a66f5e2

Please sign in to comment.