first commit

This commit is contained in:
2024-04-08 17:17:57 +00:00
commit 3e3b9a8c61
9 changed files with 296 additions and 0 deletions

35
cmd/server/api/api.go Normal file
View File

@@ -0,0 +1,35 @@
package api
import (
"fmt"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
)
type (
Server struct {
handler http.Handler
services *Services
}
Services struct {
}
)
func New(services *Services) *Server {
r := chi.NewRouter()
r.Use(middleware.RequestID)
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
return &Server{
handler: r,
services: services,
}
}
func (s *Server) ListenAndServe(port uint16) error {
return http.ListenAndServe(fmt.Sprintf(":%d", port), s.handler)
}

23
cmd/server/main.go Normal file
View File

@@ -0,0 +1,23 @@
package main
import (
"cloudsync/cmd/server/api"
"cloudsync/pkg/data"
"fmt"
"log"
"runtime"
)
const version = "0.1.0-alpha"
func main() {
fmt.Printf(" -- CloudSync server | Version %s (%s/%s) --\n\n", version, runtime.GOOS, runtime.GOARCH)
data.New("./")
server := api.New(nil)
log.Println("[INFO] starting server on port 8080")
err := server.ListenAndServe(8080)
if err != nil {
log.Fatalf("[PANIC] %s", err)
}
}

8
go.mod Normal file
View File

@@ -0,0 +1,8 @@
module cloudsync
go 1.22
require (
github.com/go-chi/chi/v5 v5.0.12
github.com/mattn/go-sqlite3 v1.14.22
)

4
go.sum Normal file
View File

@@ -0,0 +1,4 @@
github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=

58
pkg/data/data.go Normal file
View File

@@ -0,0 +1,58 @@
package data
import (
"database/sql"
"errors"
"log"
"path/filepath"
_ "github.com/mattn/go-sqlite3"
)
type (
Repository struct {
path string
conn *sql.DB
}
)
func New(path string) *Repository {
dbPath := filepath.Join(path, "system.db")
conn, err := sql.Open("sqlite3", dbPath)
if err != nil {
log.Fatal(err)
}
r := &Repository{
path: path,
conn: conn,
}
if err := r.check(); err != nil {
log.Fatalf("[PANIC] %s", err)
}
return r
}
func (r *Repository) Close() error {
return r.conn.Close()
}
func (r *Repository) check() error {
rows, err := r.conn.Query("SELECT value FROM system WHERE key = 'db.version'")
if err != nil {
m := new(migratorVersion1)
m.conn = r.conn
return m.create()
}
defer rows.Close()
var version string
if !rows.Next() {
return errors.New("no version found in the system database")
}
if err := rows.Scan(&version); err != nil {
return err
}
log.Printf("[INFO] database loaded with version %s", version)
return nil
}

40
pkg/data/db_struct_v1.sql Normal file
View File

@@ -0,0 +1,40 @@
CREATE TABLE system (
key string primary key,
value string
);
CREATE TABLE users (
uuid string primary key,
username string,
password string
);
CREATE TABLE roles (
uuid string primary key,
descriptor string
);
CREATE TABLE role_permissions (
uuid string primary key,
role string,
system_permission string
);
CREATE TABLE user_roles (
uuid string primary key,
role string,
user string
);
CREATE TABLE saves (
uuid string primary key,
name string,
user string,
path string
);
INSERT INTO system (key, value) VALUES ('db.version', '1');
INSERT INTO users (uuid, username) VALUES ('4b5b9489-973c-44e7-bae0-5ab23b56abe7', 'root');
INSERT INTO roles (uuid, descriptor) VALUES ('4b5b9489-973c-44e7-bae0-5ab23b56abe7', 'root');
INSERT INTO role_permissions (uuid, role, system_permission) VALUES ('4b5b9489-973c-44e7-bae0-5ab23b56abe7', '4b5b9489-973c-44e7-bae0-5ab23b56abe7', '*.*');
INSERT INTO user_roles (uuid, role, user) VALUES ('4b5b9489-973c-44e7-bae0-5ab23b56abe7', '4b5b9489-973c-44e7-bae0-5ab23b56abe7', '4b5b9489-973c-44e7-bae0-5ab23b56abe7');

27
pkg/data/migration.go Normal file
View File

@@ -0,0 +1,27 @@
package data
import (
"database/sql"
_ "embed"
"log"
)
//go:embed db_struct_v1.sql
var dbStructV1SQL string
type (
migratorVersion1 struct {
conn *sql.DB
}
)
func (m *migratorVersion1) create() error {
log.Printf("[INFO] no database, creating system database structure...")
_, err := m.conn.Exec(dbStructV1SQL)
if err != nil {
return err
}
log.Printf("[INFO] root user and role inserted by default")
log.Println("[INFO] database created with success!")
return nil
}

101
pkg/http/http.go Normal file
View File

@@ -0,0 +1,101 @@
package http
import (
"encoding/json"
"io"
"time"
)
type (
BaseResponse interface {
IsSuccess() bool
SentAt() time.Time
Copy(w io.Writer) error
}
Response struct {
status uint16
timestamp time.Time
}
Message struct {
Response
message string
}
Object struct {
Response
data any
}
)
func MakeResponse(status uint16) Response {
return Response{
status: status,
timestamp: time.Now(),
}
}
func MakeMessage(status uint16, message string) Message {
r := MakeResponse(status)
return Message{
Response: r,
message: message,
}
}
func MakeObject(status uint16, data any) Object {
r := MakeResponse(status)
return Object{
Response: r,
data: data,
}
}
func (r Response) IsSuccess() bool {
return r.status >= 200 && r.status < 300
}
func (r Response) SentAt() time.Time {
return r.timestamp
}
func (r Response) Copy(w io.Writer) error {
encoder := json.NewEncoder(w)
err := encoder.Encode(r)
return err
}
func (r Response) MarshalJSON() ([]byte, error) {
return json.Marshal(r.toMap())
}
func (r Response) toMap() map[string]any {
return map[string]any{
"status": r.status,
"timestamp": r.timestamp,
}
}
func (m Message) Copy(w io.Writer) error {
encoder := json.NewEncoder(w)
err := encoder.Encode(m)
return err
}
func (m Message) MarshalJSON() ([]byte, error) {
mp := m.toMap()
mp["message"] = m.message
return json.Marshal(mp)
}
func (o Object) Copy(w io.Writer) error {
encoder := json.NewEncoder(w)
err := encoder.Encode(o)
return err
}
func (o Object) MarshalJSON() ([]byte, error) {
mp := o.toMap()
mp["data"] = o.data
return json.Marshal(mp)
}

BIN
system.db Normal file

Binary file not shown.