Initial commit

This commit is contained in:
2026-02-20 23:28:42 +01:00
commit 02b494a221
16 changed files with 234 additions and 0 deletions

0
.gitignore vendored Normal file
View File

8
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

12
.idea/dataSources.xml generated Normal file
View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="database.db" uuid="0e462ae0-ce8a-4670-ab47-9f0bf5101c63">
<driver-ref>sqlite.xerial</driver-ref>
<synchronize>true</synchronize>
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
<jdbc-url>jdbc:sqlite:$PROJECT_DIR$/database.db</jdbc-url>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
</component>
</project>

7
.idea/discord.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="PROJECT_FILES" />
<option name="description" value="" />
</component>
</project>

8
.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/shap-planner-backend.iml" filepath="$PROJECT_DIR$/.idea/shap-planner-backend.iml" />
</modules>
</component>
</project>

9
.idea/shap-planner-backend.iml generated Normal file
View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="Go" enabled="true" />
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

7
.idea/sqldialects.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="SqlDialectMappings">
<file url="file://$PROJECT_DIR$/storage/storage.go" dialect="GenericSQL" />
<file url="PROJECT" dialect="SQLite" />
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

0
database.db Normal file
View File

9
go.mod Normal file
View File

@@ -0,0 +1,9 @@
module shap-planner-backend
go 1.26.0
require (
github.com/google/uuid v1.6.0
github.com/mattn/go-sqlite3 v1.14.34
golang.org/x/crypto v0.48.0
)

6
go.sum Normal file
View File

@@ -0,0 +1,6 @@
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/mattn/go-sqlite3 v1.14.34 h1:3NtcvcUnFBPsuRcno8pUtupspG/GM+9nZ88zgJcp6Zk=
github.com/mattn/go-sqlite3 v1.14.34/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=

50
handlers/account.go Normal file
View File

@@ -0,0 +1,50 @@
package handlers
import (
"encoding/json"
"net/http"
"shap-planner-backend/models"
"shap-planner-backend/storage"
"shap-planner-backend/utils"
)
func Register(w http.ResponseWriter, r *http.Request) {
var user models.User
_ = json.NewDecoder(r.Body).Decode(&user)
hashed, _ := utils.HashPassword(user.Password)
user.Password = hashed
user.ID = utils.GenerateUUID()
err := storage.AddUser(user)
if err != nil {
http.Error(w, "User exists", http.StatusBadRequest)
return
}
w.WriteHeader(http.StatusCreated)
}
func Login(w http.ResponseWriter, r *http.Request) {
var creds struct {
Username string `json:"username"`
Password string `json:"password"`
}
_ = json.NewDecoder(r.Body).Decode(&creds)
user, err := storage.GetUserByUsername(creds.Username)
if err != nil {
http.Error(w, "User not found", http.StatusUnauthorized)
return
}
if !utils.CheckPasswordHash(creds.Password, user.Password) {
http.Error(w, "Wrong password", http.StatusUnauthorized)
return
}
// TODO: JWT oder Session-Token erzeugen
w.WriteHeader(http.StatusOK)
err = json.NewEncoder(w).Encode(user)
if err != nil {
return
}
}

21
main.go Normal file
View File

@@ -0,0 +1,21 @@
package shap_planner_backend
import (
"log"
"net/http"
"shap-planner-backend/handlers"
"shap-planner-backend/storage"
)
func main() {
err := storage.InitDB("database.db")
if err != nil {
log.Fatal(err)
}
http.HandleFunc("/register", handlers.Register)
http.HandleFunc("/login", handlers.Login)
log.Println("Server läuft auf :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}

16
models/models.go Normal file
View File

@@ -0,0 +1,16 @@
package models
type User struct {
ID string `json:"id"`
Username string `json:"username"`
Password string `json:"password"`
}
type Expense struct {
ID string `json:"id"`
Amount int `json:"amt"`
Description string `json:"desc"`
Payer User `json:"payer"`
Debtors []User `json:"debtors"`
}

55
storage/storage.go Normal file
View File

@@ -0,0 +1,55 @@
package storage
import (
"database/sql"
_ "database/sql"
_ "github.com/mattn/go-sqlite3"
"shap-planner-backend/models"
_ "shap-planner-backend/models"
)
var DB *sql.DB
func InitDB(filepath string) error {
var err error
DB, err = sql.Open("sqlite3", filepath)
if err != nil {
return err
}
//Create Users-Table
_, err = DB.Exec(`CREATE TABLE IF NOT EXISTS users(
id TEXT PRIMARY KEY,
username TEXT UNIQUE,
password TEXT
);`)
if err != nil {
return err
}
//Create Expenses-Table
_, err = DB.Exec(`CREATE TABLE IF NOT EXISTS expenses(
id TEXT PRIMARY KEY
)`)
return err
}
func AddUser(user models.User) error {
_, err := DB.Exec("INSERT INTO users(id, username, password) VALUES (?, ?, ?)", user.ID, user.Username, user.Password)
return err
}
func GetUserByUsername(username string) (models.User, error) {
row := DB.QueryRow("SELECT * FROM users WHERE username = ?", username)
var user models.User
err := row.Scan(&user.ID, &user.Username, &user.Password)
return user, err
}
func GetUserById(id string) (models.User, error) {
row := DB.QueryRow("SELECT * FROM users WHERE id = ?", id)
var user models.User
err := row.Scan(&user.ID, &user.Username, &user.Password)
return user, err
}

20
utils/util.go Normal file
View File

@@ -0,0 +1,20 @@
package utils
import (
"github.com/google/uuid"
"golang.org/x/crypto/bcrypt"
)
func HashPassword(password string) (string, error) {
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
return string(bytes), err
}
func CheckPasswordHash(password, hash string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
return err == nil
}
func GenerateUUID() string {
return uuid.New().String()
}