Reorganized API + added db migrations
Read the README file for more informations
This commit is contained in:
2
backend/.gitignore
vendored
2
backend/.gitignore
vendored
@@ -1,2 +1,2 @@
|
|||||||
tmp
|
tmp
|
||||||
media
|
/media
|
||||||
|
|||||||
18
backend/README.md
Normal file
18
backend/README.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Prerequisites for development
|
||||||
|
|
||||||
|
- Installing dependencies: `go mod tidy`
|
||||||
|
- Verifying that the `.env` file is present.
|
||||||
|
|
||||||
|
## Running migrations
|
||||||
|
|
||||||
|
A migration cli is made available through the package: `./cmd/migrate`
|
||||||
|
At first it is need to run: `go run ./cmd/migrate db init` to initialize the
|
||||||
|
tables needed by golang's bun.
|
||||||
|
|
||||||
|
Then, if there migrations needed to be applied, run: `go run ./cmd/migrate db migrate`
|
||||||
|
|
||||||
|
Everything should be taken care of.
|
||||||
|
|
||||||
|
## Running the server
|
||||||
|
|
||||||
|
The server can be ran as easily as: `go run .`
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package api
|
package blogs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -7,12 +7,12 @@ import (
|
|||||||
core "fr.latosa-escrima/api/core"
|
core "fr.latosa-escrima/api/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleGetBlog(w http.ResponseWriter, r *http.Request) {
|
func HandleBlog(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
blog_uuid := r.PathValue("uuid")
|
blog_uuid := r.PathValue("uuid")
|
||||||
|
|
||||||
var blog core.Blog
|
var blog core.Blog
|
||||||
_, err := core.DB.NewSelect().
|
_, err := core.DB.NewSelect().
|
||||||
Model(&blog).
|
Model(&blog).
|
||||||
Where("blog_id = ?", blog_uuid).
|
Where("blog_id = ?", blog_uuid).
|
||||||
@@ -20,16 +20,16 @@ func HandleGetBlog(w http.ResponseWriter, r *http.Request) {
|
|||||||
ScanAndCount(context.Background())
|
ScanAndCount(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
core.JSONError{
|
core.JSONError{
|
||||||
Status: core.Error,
|
Status: core.Error,
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
}.Respond(w, http.StatusNotAcceptable)
|
}.Respond(w, http.StatusNotAcceptable)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
core.JSONSuccess{
|
core.JSONSuccess{
|
||||||
Status: core.Success,
|
Status: core.Success,
|
||||||
Message: "Status OK",
|
Message: "Status OK",
|
||||||
Data: blog,
|
Data: blog,
|
||||||
}.Respond(w, http.StatusOK)
|
}.Respond(w, http.StatusOK)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package api
|
package blogs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
core "fr.latosa-escrima/api/core"
|
core "fr.latosa-escrima/api/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleCreateBlog(w http.ResponseWriter, r *http.Request) {
|
func HandleNew(w http.ResponseWriter, r *http.Request) {
|
||||||
body, err := io.ReadAll(r.Body)
|
body, err := io.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
core.JSONError{
|
core.JSONError{
|
||||||
@@ -27,13 +27,6 @@ func (dsn *DSN) ToString() string {
|
|||||||
return fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=disable", dsn.User, dsn.Password, dsn.Hostname, dsn.Port, dsn.DBName)
|
return fmt.Sprintf("postgres://%s:%s@%s:%s/%s?sslmode=disable", dsn.User, dsn.Password, dsn.Hostname, dsn.Port, dsn.DBName)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Role string
|
|
||||||
|
|
||||||
const (
|
|
||||||
AdminRole Role = "admin"
|
|
||||||
UserRole Role = "user"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Status string
|
type Status string
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -41,20 +34,35 @@ const (
|
|||||||
Inactive Status = "Inactive"
|
Inactive Status = "Inactive"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Group string
|
||||||
|
|
||||||
|
const (
|
||||||
|
LatosaGroup Group = "latosa"
|
||||||
|
WingTsunGroup Group = "wing-tsun"
|
||||||
|
)
|
||||||
|
|
||||||
|
type UserAttributes struct {
|
||||||
|
Groups []Group `json:"groups"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PermissionConditions struct {
|
||||||
|
Groups *[]Group `json:"groups,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
bun.BaseModel `bun:"table:users"`
|
bun.BaseModel `bun:"table:users"`
|
||||||
|
|
||||||
UserID uuid.UUID `bun:"type:uuid,pk,default:gen_random_uuid()" json:"userId"`
|
UserID uuid.UUID `bun:"type:uuid,pk,default:gen_random_uuid()" json:"userId"`
|
||||||
FirstName string `bun:"firstname,notnull" json:"firstname"`
|
FirstName string `bun:"firstname,notnull" json:"firstname"`
|
||||||
LastName string `bun:"lastname,notnull" json:"lastname"`
|
LastName string `bun:"lastname,notnull" json:"lastname"`
|
||||||
Email string `bun:"email,unique,notnull" json:"email"`
|
Email string `bun:"email,unique,notnull" json:"email"`
|
||||||
Password string `bun:"password,notnull" json:"password,omitempty"`
|
Password string `bun:"password,notnull" json:"password,omitempty"`
|
||||||
Phone string `bun:"phone,notnull" json:"phone"`
|
Phone string `bun:"phone,notnull" json:"phone"`
|
||||||
Role Role `bun:"role,notnull,default:'user'" json:"role"`
|
CreatedAt time.Time `bun:"created_at,default:current_timestamp" json:"createdAt"`
|
||||||
CreatedAt time.Time `bun:"created_at,default:current_timestamp" json:"createdAt"`
|
UpdatedAt time.Time `bun:"updated_at,default:current_timestamp" json:"updatedAt"`
|
||||||
UpdatedAt time.Time `bun:"updated_at,default:current_timestamp" json:"updatedAt"`
|
Events []Event `bun:"m2m:events_to_users,join:User=Event" json:"events,omitempty"`
|
||||||
Events []Event `bun:"m2m:events_to_users,join:User=Event" json:"events,omitempty"`
|
Articles []*Blog `bun:"rel:has-many,join:user_id=blog_id" json:"articles,omitempty"`
|
||||||
Articles []*Blog `bun:"rel:has-many,join:user_id=blog_id" json:"articles,omitempty"`
|
Attributes UserAttributes `bun:"attributes,type:jsonb" json:"attributes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) Insert(ctx context.Context) (sql.Result, error) {
|
func (u *User) Insert(ctx context.Context) (sql.Result, error) {
|
||||||
@@ -66,15 +74,6 @@ func (u *User) Insert(ctx context.Context) (sql.Result, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Verify(ctx context.Context, email, password string) (*User, error) {
|
func Verify(ctx context.Context, email, password string) (*User, error) {
|
||||||
// var user User
|
|
||||||
// query := `
|
|
||||||
// SELECT *
|
|
||||||
// FROM users
|
|
||||||
// WHERE email = ? AND password = crypt(?, password)
|
|
||||||
// `
|
|
||||||
//
|
|
||||||
// err := DB.NewRaw(query, email, password).Scan(ctx, user)
|
|
||||||
|
|
||||||
var user User
|
var user User
|
||||||
count, err := DB.NewSelect().
|
count, err := DB.NewSelect().
|
||||||
Model(&user).
|
Model(&user).
|
||||||
@@ -94,6 +93,40 @@ func Verify(ctx context.Context, email, password string) (*User, error) {
|
|||||||
return &user, nil
|
return &user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Permission struct {
|
||||||
|
bun.BaseModel `bun:"table:permissions"`
|
||||||
|
ID int `bun:"id,pk,autoincrement" json:"id"`
|
||||||
|
Resource string `bun:"resource,notnull" json:"resource"`
|
||||||
|
Action string `bun:"action,notnull" json:"action"`
|
||||||
|
Conditions PermissionConditions `bun:"conditions,type:jsonb" json:"conditions"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Role struct {
|
||||||
|
bun.BaseModel `bun:"table:roles"`
|
||||||
|
ID uuid.UUID `bun:"id,pk,type:uuid,default:gen_random_uuid()" json:"id"`
|
||||||
|
Name string `bun:"name,unique,notnull" json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PermissionToRole struct {
|
||||||
|
bun.BaseModel `bun:"table:permissions_to_users"`
|
||||||
|
|
||||||
|
PermissionID int `bun:"permission_id,pk"`
|
||||||
|
RoleID uuid.UUID `bun:"type:uuid,pk"`
|
||||||
|
|
||||||
|
Permission *Permission `bun:"rel:belongs-to,join:permission_id=id"`
|
||||||
|
Role *Role `bun:"rel:belongs-to,join:role_id=id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserToRole struct {
|
||||||
|
bun.BaseModel `bun:"table:users_to_roles"`
|
||||||
|
|
||||||
|
UserID uuid.UUID `bun:"user_id,type:uuid,pk"`
|
||||||
|
RoleID uuid.UUID `bun:"type:uuid,pk"`
|
||||||
|
|
||||||
|
User *User `bun:"rel:belongs-to,join:user_id=user_id"`
|
||||||
|
Role *Role `bun:"rel:belongs-to,join:role_id=id"`
|
||||||
|
}
|
||||||
|
|
||||||
type Event struct {
|
type Event struct {
|
||||||
bun.BaseModel `bun:"table:events"`
|
bun.BaseModel `bun:"table:events"`
|
||||||
|
|
||||||
@@ -188,6 +221,8 @@ func InitDatabase(dsn DSN) (*bun.DB, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
db.RegisterModel((*EventToUser)(nil))
|
db.RegisterModel((*EventToUser)(nil))
|
||||||
|
db.RegisterModel((*PermissionToRole)(nil))
|
||||||
|
db.RegisterModel((*UserToRole)(nil))
|
||||||
_, err = db.NewCreateTable().Model((*User)(nil)).IfNotExists().Exec(ctx)
|
_, err = db.NewCreateTable().Model((*User)(nil)).IfNotExists().Exec(ctx)
|
||||||
_, err = db.NewCreateTable().Model((*Event)(nil)).IfNotExists().Exec(ctx)
|
_, err = db.NewCreateTable().Model((*Event)(nil)).IfNotExists().Exec(ctx)
|
||||||
_, err = db.NewCreateTable().Model((*EventToUser)(nil)).IfNotExists().Exec(ctx)
|
_, err = db.NewCreateTable().Model((*EventToUser)(nil)).IfNotExists().Exec(ctx)
|
||||||
@@ -195,6 +230,10 @@ func InitDatabase(dsn DSN) (*bun.DB, error) {
|
|||||||
_, err = db.NewCreateTable().Model((*WebsiteSettings)(nil)).IfNotExists().Exec(ctx)
|
_, err = db.NewCreateTable().Model((*WebsiteSettings)(nil)).IfNotExists().Exec(ctx)
|
||||||
_, err = db.NewCreateTable().Model((*Media)(nil)).IfNotExists().Exec(ctx)
|
_, err = db.NewCreateTable().Model((*Media)(nil)).IfNotExists().Exec(ctx)
|
||||||
_, err = db.NewCreateTable().Model((*Shortcode)(nil)).IfNotExists().Exec(ctx)
|
_, err = db.NewCreateTable().Model((*Shortcode)(nil)).IfNotExists().Exec(ctx)
|
||||||
|
_, err = db.NewCreateTable().Model((*Role)(nil)).IfNotExists().Exec(ctx)
|
||||||
|
_, err = db.NewCreateTable().Model((*Permission)(nil)).IfNotExists().Exec(ctx)
|
||||||
|
_, err = db.NewCreateTable().Model((*PermissionToRole)(nil)).IfNotExists().Exec(ctx)
|
||||||
|
_, err = db.NewCreateTable().Model((*UserToRole)(nil)).IfNotExists().Exec(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package api
|
package events
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"fr.latosa-escrima/api/core"
|
"fr.latosa-escrima/api/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleDeleteEvent(w http.ResponseWriter, r *http.Request) {
|
func HandleDelete(w http.ResponseWriter, r *http.Request) {
|
||||||
uuid := r.PathValue("event_uuid")
|
uuid := r.PathValue("event_uuid")
|
||||||
var event core.Event
|
var event core.Event
|
||||||
res, err := core.DB.NewDelete().
|
res, err := core.DB.NewDelete().
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package api
|
package events
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
core "fr.latosa-escrima/api/core"
|
core "fr.latosa-escrima/api/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleGetEvent(w http.ResponseWriter, r *http.Request) {
|
func HandleEvent(w http.ResponseWriter, r *http.Request) {
|
||||||
event_uuid := r.PathValue("event_uuid")
|
event_uuid := r.PathValue("event_uuid")
|
||||||
var event core.Event
|
var event core.Event
|
||||||
_, err := core.DB.NewSelect().Model(&event).Where("uuid = ?", event_uuid).ScanAndCount(context.Background())
|
_, err := core.DB.NewSelect().Model(&event).Where("uuid = ?", event_uuid).ScanAndCount(context.Background())
|
||||||
@@ -28,7 +28,7 @@ func HandleGetEvent(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func HangleGetEvents(w http.ResponseWriter, r *http.Request) {
|
func HandleEvents(w http.ResponseWriter, r *http.Request) {
|
||||||
var events []core.Event
|
var events []core.Event
|
||||||
rowsCount, err := core.DB.NewSelect().Model(&events).ScanAndCount(context.Background())
|
rowsCount, err := core.DB.NewSelect().Model(&events).ScanAndCount(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -38,7 +38,7 @@ func HangleGetEvents(w http.ResponseWriter, r *http.Request) {
|
|||||||
}.Respond(w, http.StatusInternalServerError)
|
}.Respond(w, http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
core.JSONSuccess{
|
core.JSONSuccess{
|
||||||
Status: core.Success,
|
Status: core.Success,
|
||||||
Message: fmt.Sprintf("%d Event successfully sent", rowsCount),
|
Message: fmt.Sprintf("%d Event successfully sent", rowsCount),
|
||||||
@@ -46,4 +46,3 @@ func HangleGetEvents(w http.ResponseWriter, r *http.Request) {
|
|||||||
}.Respond(w, http.StatusOK)
|
}.Respond(w, http.StatusOK)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package api
|
package events
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
core "fr.latosa-escrima/api/core"
|
core "fr.latosa-escrima/api/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleCreateEvent(w http.ResponseWriter, r *http.Request) {
|
func HandleNew(w http.ResponseWriter, r *http.Request) {
|
||||||
var event core.Event
|
var event core.Event
|
||||||
err := json.NewDecoder(r.Body).Decode(&event)
|
err := json.NewDecoder(r.Body).Decode(&event)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package api
|
package events
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleUpdateEvent(w http.ResponseWriter, r *http.Request) {
|
func HandleUpdate(w http.ResponseWriter, r *http.Request) {
|
||||||
var event core.Event
|
var event core.Event
|
||||||
err := json.NewDecoder(r.Body).Decode(&event)
|
err := json.NewDecoder(r.Body).Decode(&event)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package api
|
package media
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"fr.latosa-escrima/api/core"
|
"fr.latosa-escrima/api/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleDeleteMedia(w http.ResponseWriter, r *http.Request) {
|
func HandleDelete(w http.ResponseWriter, r *http.Request) {
|
||||||
uuid := r.PathValue("media_uuid")
|
uuid := r.PathValue("media_uuid")
|
||||||
var media core.Media
|
var media core.Media
|
||||||
res, err := core.DB.NewDelete().
|
res, err := core.DB.NewDelete().
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package api
|
package media
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
"fr.latosa-escrima/utils"
|
"fr.latosa-escrima/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleGetMedia(w http.ResponseWriter, r *http.Request) {
|
func HandleMedia(w http.ResponseWriter, r *http.Request) {
|
||||||
queryParams := r.URL.Query()
|
queryParams := r.URL.Query()
|
||||||
page, err := strconv.Atoi(queryParams.Get("page"))
|
page, err := strconv.Atoi(queryParams.Get("page"))
|
||||||
limit, err := strconv.Atoi(queryParams.Get("limit"))
|
limit, err := strconv.Atoi(queryParams.Get("limit"))
|
||||||
@@ -69,7 +69,7 @@ func HandleGetMedia(w http.ResponseWriter, r *http.Request) {
|
|||||||
}.Respond(w, http.StatusOK)
|
}.Respond(w, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleGetMediaDetails(w http.ResponseWriter, r *http.Request) {
|
func HandleMediaDetails(w http.ResponseWriter, r *http.Request) {
|
||||||
uuid := r.PathValue("media_uuid")
|
uuid := r.PathValue("media_uuid")
|
||||||
var media core.Media
|
var media core.Media
|
||||||
err := core.DB.NewSelect().
|
err := core.DB.NewSelect().
|
||||||
@@ -96,7 +96,7 @@ func HandleGetMediaDetails(w http.ResponseWriter, r *http.Request) {
|
|||||||
}.Respond(w, http.StatusOK)
|
}.Respond(w, http.StatusOK)
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleGetMediaFile(w http.ResponseWriter, r *http.Request) {
|
func HandleMediaFile(w http.ResponseWriter, r *http.Request) {
|
||||||
uuid := r.PathValue("media_uuid")
|
uuid := r.PathValue("media_uuid")
|
||||||
var media core.Media
|
var media core.Media
|
||||||
err := core.DB.NewSelect().
|
err := core.DB.NewSelect().
|
||||||
3
backend/api/media/update.go
Normal file
3
backend/api/media/update.go
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
package media
|
||||||
|
|
||||||
|
// TODO
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package api
|
package media
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleUploadMedia(w http.ResponseWriter, r *http.Request) {
|
func HandleUpload(w http.ResponseWriter, r *http.Request) {
|
||||||
// Parse the multipart form
|
// Parse the multipart form
|
||||||
err := r.ParseMultipartForm(10 << 20) // Limit file size to 10 MB
|
err := r.ParseMultipartForm(10 << 20) // Limit file size to 10 MB
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package api
|
package media
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
@@ -18,7 +18,7 @@ type FileArgs struct {
|
|||||||
SizeByte int64 `json:"size"`
|
SizeByte int64 `json:"size"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleVerifyMedia(w http.ResponseWriter, r *http.Request) {
|
func HandleVerify(w http.ResponseWriter, r *http.Request) {
|
||||||
body, err := io.ReadAll(r.Body)
|
body, err := io.ReadAll(r.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
core.JSONError{
|
core.JSONError{
|
||||||
@@ -2,99 +2,33 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
core "fr.latosa-escrima/api/core"
|
core "fr.latosa-escrima/api/core"
|
||||||
|
"fr.latosa-escrima/api/users"
|
||||||
"fr.latosa-escrima/utils"
|
"fr.latosa-escrima/utils"
|
||||||
"github.com/golang-jwt/jwt/v5"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
var MySigningKey = []byte("COUCOU")
|
func CORS(next http.Handler) http.Handler {
|
||||||
|
CORS_AllowOrigin := os.Getenv("CORS_AllowOrigin")
|
||||||
type LoginArgs struct {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
Email string `json:"email"`
|
// Allow all origins (can restrict to specific origins)
|
||||||
Password string `json:"password"`
|
w.Header().Set("Access-Control-Allow-Origin", CORS_AllowOrigin)
|
||||||
}
|
// Allow certain HTTP methods (you can customize these as needed)
|
||||||
|
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH")
|
||||||
type Claims struct {
|
// Allow certain headers (you can add more as needed)
|
||||||
UserID string `json:"user_id"`
|
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization, X-CSRF-Token")
|
||||||
jwt.RegisteredClaims
|
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
||||||
}
|
// Handle OPTIONS pre-flight request
|
||||||
|
if r.Method == http.MethodOptions {
|
||||||
func HandleLogin(w http.ResponseWriter, r *http.Request) {
|
return
|
||||||
if r.Body == nil {
|
}
|
||||||
core.JSONError{
|
next.ServeHTTP(w, r)
|
||||||
Status: core.Error,
|
})
|
||||||
Message: "No body has been provided.",
|
|
||||||
}.Respond(w, http.StatusNoContent)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
body, err := io.ReadAll(r.Body)
|
|
||||||
fmt.Println(body)
|
|
||||||
if err != nil {
|
|
||||||
core.JSONError{
|
|
||||||
Status: core.Error,
|
|
||||||
Message: err.Error(),
|
|
||||||
}.Respond(w, http.StatusNoContent)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var login LoginArgs
|
|
||||||
err = json.Unmarshal(body, &login)
|
|
||||||
if err != nil {
|
|
||||||
core.JSONError{
|
|
||||||
Status: core.Error,
|
|
||||||
Message: err.Error(),
|
|
||||||
}.Respond(w, http.StatusNoContent)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user, err := core.Verify(context.Background(), login.Email, login.Password)
|
|
||||||
if user == nil {
|
|
||||||
core.JSONError{
|
|
||||||
Status: core.Error,
|
|
||||||
Message: "User not found.",
|
|
||||||
}.Respond(w, http.StatusNotFound)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
core.JSONError{
|
|
||||||
Status: core.Error,
|
|
||||||
Message: err.Error(),
|
|
||||||
}.Respond(w, http.StatusNoContent)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
claims := Claims{
|
|
||||||
UserID: user.UserID.String(),
|
|
||||||
RegisteredClaims: jwt.RegisteredClaims{
|
|
||||||
Issuer: "latosa-escrima.fr",
|
|
||||||
Subject: "authentification",
|
|
||||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * 24)),
|
|
||||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
|
||||||
signed, err := token.SignedString(MySigningKey)
|
|
||||||
if err != nil {
|
|
||||||
core.JSONError{
|
|
||||||
Status: core.Error,
|
|
||||||
Message: err.Error(),
|
|
||||||
}.Respond(w, http.StatusNoContent)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
core.JSONSuccess{
|
|
||||||
Status: core.Success,
|
|
||||||
Message: "JWT Created",
|
|
||||||
Data: signed,
|
|
||||||
}.Respond(w, http.StatusCreated)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func AuthJWT(next http.Handler) http.Handler {
|
func AuthJWT(next http.Handler) http.Handler {
|
||||||
@@ -125,7 +59,7 @@ func AuthJWT(next http.Handler) http.Handler {
|
|||||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||||
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
||||||
}
|
}
|
||||||
return MySigningKey, nil
|
return users.MySigningKey, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil || !token.Valid {
|
if err != nil || !token.Valid {
|
||||||
1
backend/api/permissions/delete.go
Normal file
1
backend/api/permissions/delete.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package permissions
|
||||||
1
backend/api/permissions/new.go
Normal file
1
backend/api/permissions/new.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package permissions
|
||||||
1
backend/api/permissions/permission.go
Normal file
1
backend/api/permissions/permission.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package permissions
|
||||||
1
backend/api/permissions/permissions.go
Normal file
1
backend/api/permissions/permissions.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package permissions
|
||||||
1
backend/api/permissions/update.go
Normal file
1
backend/api/permissions/update.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package permissions
|
||||||
1
backend/api/roles/add_permission.go
Normal file
1
backend/api/roles/add_permission.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package roles
|
||||||
1
backend/api/roles/delete.go
Normal file
1
backend/api/roles/delete.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package roles
|
||||||
1
backend/api/roles/new.go
Normal file
1
backend/api/roles/new.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package roles
|
||||||
1
backend/api/roles/permissions.go
Normal file
1
backend/api/roles/permissions.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package roles
|
||||||
1
backend/api/roles/remove_permission.go
Normal file
1
backend/api/roles/remove_permission.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package roles
|
||||||
1
backend/api/roles/role.go
Normal file
1
backend/api/roles/role.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package roles
|
||||||
1
backend/api/roles/roles.go
Normal file
1
backend/api/roles/roles.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package roles
|
||||||
1
backend/api/roles/update.go
Normal file
1
backend/api/roles/update.go
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package roles
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package api
|
package shortcodes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
core "fr.latosa-escrima/api/core"
|
core "fr.latosa-escrima/api/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleDeleteShortcode(w http.ResponseWriter, r *http.Request) {
|
func HandleDelete(w http.ResponseWriter, r *http.Request) {
|
||||||
code := r.PathValue("shortcode")
|
code := r.PathValue("shortcode")
|
||||||
_, err := core.DB.NewDelete().
|
_, err := core.DB.NewDelete().
|
||||||
Model((*core.Shortcode)(nil)).
|
Model((*core.Shortcode)(nil)).
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package api
|
package shortcodes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"fr.latosa-escrima/api/core"
|
"fr.latosa-escrima/api/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleCreateShortcode(w http.ResponseWriter, r *http.Request) {
|
func HandleNew(w http.ResponseWriter, r *http.Request) {
|
||||||
var shortcode core.Shortcode
|
var shortcode core.Shortcode
|
||||||
err := json.NewDecoder(r.Body).Decode(&shortcode)
|
err := json.NewDecoder(r.Body).Decode(&shortcode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package api
|
package shortcodes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"fr.latosa-escrima/api/core"
|
"fr.latosa-escrima/api/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleGetShortcode(w http.ResponseWriter, r *http.Request) {
|
func HandleShortcode(w http.ResponseWriter, r *http.Request) {
|
||||||
code := r.PathValue("shortcode")
|
code := r.PathValue("shortcode")
|
||||||
var shortcode core.Shortcode
|
var shortcode core.Shortcode
|
||||||
err := core.DB.NewSelect().
|
err := core.DB.NewSelect().
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package api
|
package shortcodes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"fr.latosa-escrima/api/core"
|
"fr.latosa-escrima/api/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleGetShortcodes(w http.ResponseWriter, r *http.Request) {
|
func HandleShortcodes(w http.ResponseWriter, r *http.Request) {
|
||||||
var shortcodes []core.Shortcode
|
var shortcodes []core.Shortcode
|
||||||
err := core.DB.NewSelect().Model(&shortcodes).Scan(context.Background())
|
err := core.DB.NewSelect().Model(&shortcodes).Scan(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package api
|
package shortcodes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -20,7 +20,7 @@ type UpdateShortcodeArgs struct {
|
|||||||
MediaID *uuid.UUID `json:"media_id,omitempty"` // Nullable reference to another table's ID
|
MediaID *uuid.UUID `json:"media_id,omitempty"` // Nullable reference to another table's ID
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleUpdateShortcode(w http.ResponseWriter, r *http.Request) {
|
func HandleUpdate(w http.ResponseWriter, r *http.Request) {
|
||||||
var updateArgs UpdateShortcodeArgs
|
var updateArgs UpdateShortcodeArgs
|
||||||
err := json.NewDecoder(r.Body).Decode(&updateArgs)
|
err := json.NewDecoder(r.Body).Decode(&updateArgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
96
backend/api/users/auth.go
Normal file
96
backend/api/users/auth.go
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
package users
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
core "fr.latosa-escrima/api/core"
|
||||||
|
"github.com/golang-jwt/jwt/v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
var MySigningKey = []byte("COUCOU")
|
||||||
|
|
||||||
|
type LoginArgs struct {
|
||||||
|
Email string `json:"email"`
|
||||||
|
Password string `json:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Claims struct {
|
||||||
|
UserID string `json:"user_id"`
|
||||||
|
jwt.RegisteredClaims
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandleLogin(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Body == nil {
|
||||||
|
core.JSONError{
|
||||||
|
Status: core.Error,
|
||||||
|
Message: "No body has been provided.",
|
||||||
|
}.Respond(w, http.StatusNoContent)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := io.ReadAll(r.Body)
|
||||||
|
fmt.Println(body)
|
||||||
|
if err != nil {
|
||||||
|
core.JSONError{
|
||||||
|
Status: core.Error,
|
||||||
|
Message: err.Error(),
|
||||||
|
}.Respond(w, http.StatusNoContent)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var login LoginArgs
|
||||||
|
err = json.Unmarshal(body, &login)
|
||||||
|
if err != nil {
|
||||||
|
core.JSONError{
|
||||||
|
Status: core.Error,
|
||||||
|
Message: err.Error(),
|
||||||
|
}.Respond(w, http.StatusNoContent)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := core.Verify(context.Background(), login.Email, login.Password)
|
||||||
|
if user == nil {
|
||||||
|
core.JSONError{
|
||||||
|
Status: core.Error,
|
||||||
|
Message: "User not found.",
|
||||||
|
}.Respond(w, http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
core.JSONError{
|
||||||
|
Status: core.Error,
|
||||||
|
Message: err.Error(),
|
||||||
|
}.Respond(w, http.StatusNoContent)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
claims := Claims{
|
||||||
|
UserID: user.UserID.String(),
|
||||||
|
RegisteredClaims: jwt.RegisteredClaims{
|
||||||
|
Issuer: "latosa-escrima.fr",
|
||||||
|
Subject: "authentification",
|
||||||
|
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * 24)),
|
||||||
|
IssuedAt: jwt.NewNumericDate(time.Now()),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||||
|
signed, err := token.SignedString(MySigningKey)
|
||||||
|
if err != nil {
|
||||||
|
core.JSONError{
|
||||||
|
Status: core.Error,
|
||||||
|
Message: err.Error(),
|
||||||
|
}.Respond(w, http.StatusNoContent)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
core.JSONSuccess{
|
||||||
|
Status: core.Success,
|
||||||
|
Message: "JWT Created",
|
||||||
|
Data: signed,
|
||||||
|
}.Respond(w, http.StatusCreated)
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package api
|
package users
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"fr.latosa-escrima/api/core"
|
"fr.latosa-escrima/api/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleDeleteUser(w http.ResponseWriter, r *http.Request) {
|
func HandleDelete(w http.ResponseWriter, r *http.Request) {
|
||||||
uuid := r.PathValue("user_uuid")
|
uuid := r.PathValue("user_uuid")
|
||||||
_, err := core.DB.NewDelete().
|
_, err := core.DB.NewDelete().
|
||||||
Model((*core.User)(nil)).
|
Model((*core.User)(nil)).
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package api
|
package users
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"github.com/golang-jwt/jwt/v5"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleGetMe(w http.ResponseWriter, r *http.Request) {
|
func HandleMe(w http.ResponseWriter, r *http.Request) {
|
||||||
token, ok := r.Context().Value("token").(*jwt.Token)
|
token, ok := r.Context().Value("token").(*jwt.Token)
|
||||||
if !ok {
|
if !ok {
|
||||||
core.JSONError{
|
core.JSONError{
|
||||||
@@ -29,5 +29,5 @@ func HandleGetMe(w http.ResponseWriter, r *http.Request) {
|
|||||||
uuid := claims["user_id"].(string)
|
uuid := claims["user_id"].(string)
|
||||||
|
|
||||||
r.SetPathValue("user_uuid", uuid)
|
r.SetPathValue("user_uuid", uuid)
|
||||||
HandleGetUser(w, r)
|
HandleUser(w, r)
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package api
|
package users
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
core "fr.latosa-escrima/api/core"
|
core "fr.latosa-escrima/api/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleCreateUser(w http.ResponseWriter, r *http.Request) {
|
func HandleNew(w http.ResponseWriter, r *http.Request) {
|
||||||
var user core.User
|
var user core.User
|
||||||
err := json.NewDecoder(r.Body).Decode(&user)
|
err := json.NewDecoder(r.Body).Decode(&user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package api
|
package users
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -13,15 +13,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type UpdateUserArgs struct {
|
type UpdateUserArgs struct {
|
||||||
FirstName *string `json:"firstname,omitempty"`
|
FirstName *string `json:"firstname,omitempty"`
|
||||||
LastName *string `json:"lastname,omitempty"`
|
LastName *string `json:"lastname,omitempty"`
|
||||||
Email *string `json:"email,omitempty"`
|
Email *string `json:"email,omitempty"`
|
||||||
Password *string `json:"password,omitempty"`
|
Password *string `json:"password,omitempty"`
|
||||||
Phone *string `json:"phone,omitempty"`
|
Phone *string `json:"phone,omitempty"`
|
||||||
Role *core.Role `json:"role,omitempty"`
|
Attributes *core.UserAttributes `json:"attributes"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleUpdateUser(w http.ResponseWriter, r *http.Request) {
|
func HandleUpdate(w http.ResponseWriter, r *http.Request) {
|
||||||
var updateArgs UpdateUserArgs
|
var updateArgs UpdateUserArgs
|
||||||
err := json.NewDecoder(r.Body).Decode(&updateArgs)
|
err := json.NewDecoder(r.Body).Decode(&updateArgs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package api
|
package users
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"fr.latosa-escrima/api/core"
|
"fr.latosa-escrima/api/core"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleGetUser(w http.ResponseWriter, r *http.Request) {
|
func HandleUser(w http.ResponseWriter, r *http.Request) {
|
||||||
uuid := r.PathValue("user_uuid")
|
uuid := r.PathValue("user_uuid")
|
||||||
var user core.User
|
var user core.User
|
||||||
count, err := core.DB.NewSelect().
|
count, err := core.DB.NewSelect().
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package api
|
package users
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
"fr.latosa-escrima/utils"
|
"fr.latosa-escrima/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func HandleGetUsers(w http.ResponseWriter, r *http.Request) {
|
func HandleUsers(w http.ResponseWriter, r *http.Request) {
|
||||||
var users []core.User
|
var users []core.User
|
||||||
count, err := core.DB.NewSelect().
|
count, err := core.DB.NewSelect().
|
||||||
Model(&users).
|
Model(&users).
|
||||||
219
backend/cmd/migrate/main.go
Normal file
219
backend/cmd/migrate/main.go
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"fr.latosa-escrima/api/core"
|
||||||
|
"fr.latosa-escrima/cmd/migrate/migrations"
|
||||||
|
"github.com/joho/godotenv"
|
||||||
|
"github.com/uptrace/bun/dialect/pgdialect"
|
||||||
|
"github.com/uptrace/bun/driver/pgdriver"
|
||||||
|
"github.com/uptrace/bun/extra/bundebug"
|
||||||
|
"github.com/uptrace/bun/migrate"
|
||||||
|
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
|
||||||
|
"github.com/uptrace/bun"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
err := godotenv.Load()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("Error loading .env file: %v", err)
|
||||||
|
}
|
||||||
|
environ := os.Getenv("ENVIRONMENT")
|
||||||
|
|
||||||
|
hostname := os.Getenv("DATABASE_HOSTNAME")
|
||||||
|
postgres_port := os.Getenv("POSTGRES_DOCKER_PORT")
|
||||||
|
if environ == "DEV" {
|
||||||
|
hostname = "localhost"
|
||||||
|
postgres_port = os.Getenv("POSTGRES_PORT")
|
||||||
|
}
|
||||||
|
|
||||||
|
dsn := core.DSN{
|
||||||
|
Hostname: hostname,
|
||||||
|
Port: postgres_port,
|
||||||
|
DBName: os.Getenv("POSTGRES_DB"),
|
||||||
|
User: os.Getenv("POSTGRES_USER"),
|
||||||
|
Password: os.Getenv("POSTGRES_PASSWORD"),
|
||||||
|
}
|
||||||
|
fmt.Println(dsn.ToString())
|
||||||
|
sqldb := sql.OpenDB(pgdriver.NewConnector(pgdriver.WithDSN(dsn.ToString())))
|
||||||
|
db := bun.NewDB(sqldb, pgdialect.New())
|
||||||
|
|
||||||
|
db.AddQueryHook(bundebug.NewQueryHook(bundebug.WithVerbose(true)))
|
||||||
|
|
||||||
|
defer db.Close()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
db.AddQueryHook(bundebug.NewQueryHook(
|
||||||
|
bundebug.WithEnabled(false),
|
||||||
|
bundebug.FromEnv(),
|
||||||
|
))
|
||||||
|
|
||||||
|
app := &cli.App{
|
||||||
|
Name: "bun",
|
||||||
|
|
||||||
|
Commands: []*cli.Command{
|
||||||
|
newDBCommand(migrate.NewMigrator(db, migrations.Migrations)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if err := app.Run(os.Args); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newDBCommand(migrator *migrate.Migrator) *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
|
Name: "db",
|
||||||
|
Usage: "database migrations",
|
||||||
|
Subcommands: []*cli.Command{
|
||||||
|
{
|
||||||
|
Name: "init",
|
||||||
|
Usage: "create migration tables",
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
return migrator.Init(c.Context)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "migrate",
|
||||||
|
Usage: "migrate database",
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
if err := migrator.Lock(c.Context); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer migrator.Unlock(c.Context) //nolint:errcheck
|
||||||
|
|
||||||
|
group, err := migrator.Migrate(c.Context)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if group.IsZero() {
|
||||||
|
fmt.Printf("there are no new migrations to run (database is up to date)\n")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
fmt.Printf("migrated to %s\n", group)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "rollback",
|
||||||
|
Usage: "rollback the last migration group",
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
if err := migrator.Lock(c.Context); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer migrator.Unlock(c.Context) //nolint:errcheck
|
||||||
|
|
||||||
|
group, err := migrator.Rollback(c.Context)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if group.IsZero() {
|
||||||
|
fmt.Printf("there are no groups to roll back\n")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
fmt.Printf("rolled back %s\n", group)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "lock",
|
||||||
|
Usage: "lock migrations",
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
return migrator.Lock(c.Context)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "unlock",
|
||||||
|
Usage: "unlock migrations",
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
return migrator.Unlock(c.Context)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "create_go",
|
||||||
|
Usage: "create Go migration",
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
name := strings.Join(c.Args().Slice(), "_")
|
||||||
|
mf, err := migrator.CreateGoMigration(c.Context, name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("created migration %s (%s)\n", mf.Name, mf.Path)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "create_sql",
|
||||||
|
Usage: "create up and down SQL migrations",
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
name := strings.Join(c.Args().Slice(), "_")
|
||||||
|
files, err := migrator.CreateSQLMigrations(c.Context, name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, mf := range files {
|
||||||
|
fmt.Printf("created migration %s (%s)\n", mf.Name, mf.Path)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "create_tx_sql",
|
||||||
|
Usage: "create up and down transactional SQL migrations",
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
name := strings.Join(c.Args().Slice(), "_")
|
||||||
|
files, err := migrator.CreateTxSQLMigrations(c.Context, name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, mf := range files {
|
||||||
|
fmt.Printf("created transaction migration %s (%s)\n", mf.Name, mf.Path)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "status",
|
||||||
|
Usage: "print migrations status",
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
ms, err := migrator.MigrationsWithStatus(c.Context)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Printf("migrations: %s\n", ms)
|
||||||
|
fmt.Printf("unapplied migrations: %s\n", ms.Unapplied())
|
||||||
|
fmt.Printf("last migration group: %s\n", ms.LastGroup())
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "mark_applied",
|
||||||
|
Usage: "mark migrations as applied without actually running them",
|
||||||
|
Action: func(c *cli.Context) error {
|
||||||
|
group, err := migrator.Migrate(c.Context, migrate.WithNopMigration())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if group.IsZero() {
|
||||||
|
fmt.Printf("there are no new migrations to mark as applied\n")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
fmt.Printf("marked as applied %s\n", group)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE users DROP COLUMN attributes;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE users ADD COLUMN attributes jsonb;
|
||||||
11
backend/cmd/migrate/migrations/main.go
Normal file
11
backend/cmd/migrate/migrations/main.go
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
package migrations
|
||||||
|
|
||||||
|
import "github.com/uptrace/bun/migrate"
|
||||||
|
|
||||||
|
var Migrations = migrate.NewMigrations()
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if err := Migrations.DiscoverCaller(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,6 +12,12 @@ require (
|
|||||||
github.com/uptrace/bun/driver/pgdriver v1.2.8
|
github.com/uptrace/bun/driver/pgdriver v1.2.8
|
||||||
)
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
|
||||||
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gorilla/csrf v1.7.2 // direct
|
github.com/gorilla/csrf v1.7.2 // direct
|
||||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||||
@@ -26,6 +32,7 @@ require (
|
|||||||
github.com/puzpuzpuz/xsync/v3 v3.4.0 // indirect
|
github.com/puzpuzpuz/xsync/v3 v3.4.0 // indirect
|
||||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
|
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
|
||||||
github.com/uptrace/bun/extra/bundebug v1.2.8 // direct
|
github.com/uptrace/bun/extra/bundebug v1.2.8 // direct
|
||||||
|
github.com/urfave/cli/v2 v2.27.5
|
||||||
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
|
github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
|
||||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||||
golang.org/x/crypto v0.31.0 // indirect
|
golang.org/x/crypto v0.31.0 // indirect
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
|
||||||
|
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||||
@@ -27,6 +29,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/puzpuzpuz/xsync/v3 v3.4.0 h1:DuVBAdXuGFHv8adVXjWWZ63pJq+NRXOWVXlKDBZ+mJ4=
|
github.com/puzpuzpuz/xsync/v3 v3.4.0 h1:DuVBAdXuGFHv8adVXjWWZ63pJq+NRXOWVXlKDBZ+mJ4=
|
||||||
github.com/puzpuzpuz/xsync/v3 v3.4.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
|
github.com/puzpuzpuz/xsync/v3 v3.4.0/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
|
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
|
||||||
@@ -39,10 +43,14 @@ github.com/uptrace/bun/driver/pgdriver v1.2.8 h1:5XrNn/9enSrWhhrUpz+6PY9S1vcg/jh
|
|||||||
github.com/uptrace/bun/driver/pgdriver v1.2.8/go.mod h1:cwRRwqabgePwYBiLlXtbeNmPD7LGJnqP21J2ZKP4ah8=
|
github.com/uptrace/bun/driver/pgdriver v1.2.8/go.mod h1:cwRRwqabgePwYBiLlXtbeNmPD7LGJnqP21J2ZKP4ah8=
|
||||||
github.com/uptrace/bun/extra/bundebug v1.2.8 h1:Epv0ycLOnoKWPky+rufP2F/PrcSlKkd4tmVIFOdq90A=
|
github.com/uptrace/bun/extra/bundebug v1.2.8 h1:Epv0ycLOnoKWPky+rufP2F/PrcSlKkd4tmVIFOdq90A=
|
||||||
github.com/uptrace/bun/extra/bundebug v1.2.8/go.mod h1:ucnmuPw/5ePbNFj2SPmV0lQh3ZvL+3HCrpvRxIYZyWQ=
|
github.com/uptrace/bun/extra/bundebug v1.2.8/go.mod h1:ucnmuPw/5ePbNFj2SPmV0lQh3ZvL+3HCrpvRxIYZyWQ=
|
||||||
|
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
|
||||||
|
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
|
||||||
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
|
github.com/vmihailenco/msgpack/v5 v5.4.1 h1:cQriyiUvjTwOHg8QZaPihLWeRAAVoCpE00IUPn0Bjt8=
|
||||||
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
|
github.com/vmihailenco/msgpack/v5 v5.4.1/go.mod h1:GaZTsDaehaPpQVyxrf5mtQlH+pc21PIudVV/E3rRQok=
|
||||||
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
|
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
|
||||||
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
|
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
|
||||||
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
|
||||||
|
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
|
||||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
|||||||
128
backend/main.go
128
backend/main.go
@@ -12,7 +12,12 @@ import (
|
|||||||
_ "github.com/lib/pq"
|
_ "github.com/lib/pq"
|
||||||
|
|
||||||
"fr.latosa-escrima/api"
|
"fr.latosa-escrima/api"
|
||||||
|
"fr.latosa-escrima/api/blogs"
|
||||||
"fr.latosa-escrima/api/core"
|
"fr.latosa-escrima/api/core"
|
||||||
|
"fr.latosa-escrima/api/events"
|
||||||
|
"fr.latosa-escrima/api/media"
|
||||||
|
"fr.latosa-escrima/api/shortcodes"
|
||||||
|
"fr.latosa-escrima/api/users"
|
||||||
"github.com/gorilla/csrf"
|
"github.com/gorilla/csrf"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -21,22 +26,6 @@ var CORS_AllowOrigin string
|
|||||||
func handler(w http.ResponseWriter, r *http.Request) {
|
func handler(w http.ResponseWriter, r *http.Request) {
|
||||||
fmt.Fprintf(w, "<html><body><h1>Hello, World!</h1></body></html>")
|
fmt.Fprintf(w, "<html><body><h1>Hello, World!</h1></body></html>")
|
||||||
}
|
}
|
||||||
func Cors(next http.Handler) http.Handler {
|
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
// Allow all origins (can restrict to specific origins)
|
|
||||||
w.Header().Set("Access-Control-Allow-Origin", CORS_AllowOrigin)
|
|
||||||
// Allow certain HTTP methods (you can customize these as needed)
|
|
||||||
w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, PATCH")
|
|
||||||
// Allow certain headers (you can add more as needed)
|
|
||||||
w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization, X-CSRF-Token")
|
|
||||||
w.Header().Set("Access-Control-Allow-Credentials", "true")
|
|
||||||
// Handle OPTIONS pre-flight request
|
|
||||||
if r.Method == http.MethodOptions {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
next.ServeHTTP(w, r)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
err := godotenv.Load()
|
err := godotenv.Load()
|
||||||
@@ -48,7 +37,6 @@ func main() {
|
|||||||
port := os.Getenv("BACKEND_DOCKER_PORT")
|
port := os.Getenv("BACKEND_DOCKER_PORT")
|
||||||
hostname := os.Getenv("DATABASE_HOSTNAME")
|
hostname := os.Getenv("DATABASE_HOSTNAME")
|
||||||
postgres_port := os.Getenv("POSTGRES_DOCKER_PORT")
|
postgres_port := os.Getenv("POSTGRES_DOCKER_PORT")
|
||||||
CORS_AllowOrigin = os.Getenv("CORS_AllowOrigin")
|
|
||||||
if environ == "DEV" {
|
if environ == "DEV" {
|
||||||
port = os.Getenv("BACKEND_PORT")
|
port = os.Getenv("BACKEND_PORT")
|
||||||
hostname = "localhost"
|
hostname = "localhost"
|
||||||
@@ -85,67 +73,67 @@ func main() {
|
|||||||
Handler: handler,
|
Handler: handler,
|
||||||
Middlewares: []core.Middleware{api.Methods("get")}},
|
Middlewares: []core.Middleware{api.Methods("get")}},
|
||||||
"/users/login": {
|
"/users/login": {
|
||||||
Handler: api.HandleLogin,
|
Handler: users.HandleLogin,
|
||||||
Middlewares: []core.Middleware{api.Methods("POST")}},
|
Middlewares: []core.Middleware{api.Methods("POST")}},
|
||||||
"/users/me": {
|
"/users/me": {
|
||||||
Handler: api.HandleGetMe,
|
Handler: users.HandleMe,
|
||||||
Middlewares: []core.Middleware{api.Methods("GET"), api.AuthJWT}},
|
Middlewares: []core.Middleware{api.Methods("GET"), api.AuthJWT}},
|
||||||
"/users": {
|
"/users": {
|
||||||
Handler: api.HandleGetUsers,
|
Handler: users.HandleUsers,
|
||||||
Middlewares: []core.Middleware{api.Methods("GET"), api.AuthJWT}},
|
Middlewares: []core.Middleware{api.Methods("GET"), api.AuthJWT}},
|
||||||
"/users/new": {
|
"/users/new": {
|
||||||
Handler: api.HandleCreateUser,
|
Handler: users.HandleNew,
|
||||||
Middlewares: []core.Middleware{api.Methods("POST"), api.AuthJWT}},
|
Middlewares: []core.Middleware{api.Methods("POST"), api.AuthJWT}},
|
||||||
"/users/{user_uuid}": {
|
"/users/{user_uuid}": {
|
||||||
Handler: api.HandleGetUser,
|
Handler: users.HandleUser,
|
||||||
Middlewares: []core.Middleware{api.Methods("GET"), api.AuthJWT}},
|
Middlewares: []core.Middleware{api.Methods("GET"), api.AuthJWT}},
|
||||||
"/users/{user_uuid}/delete": {
|
"/users/{user_uuid}/delete": {
|
||||||
Handler: api.HandleDeleteUser,
|
Handler: users.HandleDelete,
|
||||||
Middlewares: []core.Middleware{api.Methods("DELETE"), api.AuthJWT}},
|
Middlewares: []core.Middleware{api.Methods("DELETE"), api.AuthJWT}},
|
||||||
"/users/{user_uuid}/update": {
|
"/users/{user_uuid}/update": {
|
||||||
Handler: api.HandleUpdateUser,
|
Handler: users.HandleUpdate,
|
||||||
Middlewares: []core.Middleware{api.Methods("PATCH"), api.AuthJWT}},
|
Middlewares: []core.Middleware{api.Methods("PATCH"), api.AuthJWT}},
|
||||||
"/events": {
|
"/events": {
|
||||||
Handler: api.HangleGetEvents,
|
Handler: events.HandleEvents,
|
||||||
Middlewares: []core.Middleware{api.Methods("GET")}},
|
Middlewares: []core.Middleware{api.Methods("GET")}},
|
||||||
"/events/new": {
|
"/events/new": {
|
||||||
Handler: api.HandleCreateEvent,
|
Handler: events.HandleNew,
|
||||||
Middlewares: []core.Middleware{api.Methods("POST")}},
|
Middlewares: []core.Middleware{api.Methods("POST")}},
|
||||||
"/events/{event_uuid}": {
|
"/events/{event_uuid}": {
|
||||||
Handler: api.HandleGetEvent,
|
Handler: events.HandleEvent,
|
||||||
Middlewares: []core.Middleware{api.Methods("GET")}},
|
Middlewares: []core.Middleware{api.Methods("GET")}},
|
||||||
"/events/{event_uuid}/delete": {
|
"/events/{event_uuid}/delete": {
|
||||||
Handler: api.HandleDeleteEvent,
|
Handler: events.HandleDelete,
|
||||||
Middlewares: []core.Middleware{api.Methods("DELETE")}},
|
Middlewares: []core.Middleware{api.Methods("DELETE")}},
|
||||||
"/events/{event_uuid}/update": {
|
"/events/{event_uuid}/update": {
|
||||||
Handler: api.HandleUpdateEvent,
|
Handler: events.HandleUpdate,
|
||||||
Middlewares: []core.Middleware{api.Methods("PATCH")}},
|
Middlewares: []core.Middleware{api.Methods("PATCH")}},
|
||||||
"/blogs/new": {
|
"/blogs/new": {
|
||||||
Handler: api.HandleCreateBlog,
|
Handler: blogs.HandleNew,
|
||||||
Middlewares: []core.Middleware{api.Methods(("POST"))}},
|
Middlewares: []core.Middleware{api.Methods(("POST"))}},
|
||||||
"/blogs/{uuid}": {
|
"/blogs/{uuid}": {
|
||||||
Handler: api.HandleGetBlog,
|
Handler: blogs.HandleBlog,
|
||||||
Middlewares: []core.Middleware{api.Methods("GET")}},
|
Middlewares: []core.Middleware{api.Methods("GET")}},
|
||||||
"/media/upload": {
|
"/media/upload": {
|
||||||
Handler: api.HandleUploadMedia,
|
Handler: media.HandleUpload,
|
||||||
Middlewares: []core.Middleware{api.Methods("POST"), api.AuthJWT}},
|
Middlewares: []core.Middleware{api.Methods("POST"), api.AuthJWT}},
|
||||||
"/media/verify": {
|
"/media/verify": {
|
||||||
Handler: api.HandleVerifyMedia,
|
Handler: media.HandleVerify,
|
||||||
Middlewares: []core.Middleware{api.Methods("POST"), api.AuthJWT},
|
Middlewares: []core.Middleware{api.Methods("POST"), api.AuthJWT},
|
||||||
},
|
},
|
||||||
// Paginated media response
|
// Paginated media response
|
||||||
"/media/": {
|
"/media/": {
|
||||||
Handler: api.HandleGetMedia,
|
Handler: media.HandleMedia,
|
||||||
Middlewares: []core.Middleware{api.Methods("GET")},
|
Middlewares: []core.Middleware{api.Methods("GET")},
|
||||||
},
|
},
|
||||||
// Unique element
|
// Unique element
|
||||||
"/media/{media_uuid}": {
|
"/media/{media_uuid}": {
|
||||||
Handler: api.HandleGetMediaDetails,
|
Handler: media.HandleMediaDetails,
|
||||||
Middlewares: []core.Middleware{api.Methods("GET")},
|
Middlewares: []core.Middleware{api.Methods("GET")},
|
||||||
},
|
},
|
||||||
// Get the image, video, GIF etc.
|
// Get the image, video, GIF etc.
|
||||||
"/media/{media_uuid}/file": {
|
"/media/{media_uuid}/file": {
|
||||||
Handler: api.HandleGetMediaFile,
|
Handler: media.HandleMediaFile,
|
||||||
Middlewares: []core.Middleware{api.Methods("GET")},
|
Middlewares: []core.Middleware{api.Methods("GET")},
|
||||||
},
|
},
|
||||||
// "/media/{media_uuid}/update": {
|
// "/media/{media_uuid}/update": {
|
||||||
@@ -153,29 +141,81 @@ func main() {
|
|||||||
// Middlewares: []core.Middleware{api.Methods("PATCH"), api.AuthJWT},
|
// Middlewares: []core.Middleware{api.Methods("PATCH"), api.AuthJWT},
|
||||||
// },
|
// },
|
||||||
"/media/{media_uuid}/delete": {
|
"/media/{media_uuid}/delete": {
|
||||||
Handler: api.HandleDeleteMedia,
|
Handler: media.HandleDelete,
|
||||||
Middlewares: []core.Middleware{api.Methods("DELETE"), api.AuthJWT},
|
Middlewares: []core.Middleware{api.Methods("DELETE"), api.AuthJWT},
|
||||||
},
|
},
|
||||||
"/shortcodes/new": {
|
"/shortcodes/new": {
|
||||||
Handler: api.HandleCreateShortcode,
|
Handler: shortcodes.HandleNew,
|
||||||
Middlewares: []core.Middleware{api.Methods("POST"), api.AuthJWT},
|
Middlewares: []core.Middleware{api.Methods("POST"), api.AuthJWT},
|
||||||
},
|
},
|
||||||
"/shortcodes/": {
|
"/shortcodes/": {
|
||||||
Handler: api.HandleGetShortcodes,
|
Handler: shortcodes.HandleShortcodes,
|
||||||
Middlewares: []core.Middleware{api.Methods("GET"), api.AuthJWT},
|
Middlewares: []core.Middleware{api.Methods("GET"), api.AuthJWT},
|
||||||
},
|
},
|
||||||
"/shortcodes/{shortcode}": {
|
"/shortcodes/{shortcode}": {
|
||||||
Handler: api.HandleGetShortcode,
|
Handler: shortcodes.HandleShortcode,
|
||||||
Middlewares: []core.Middleware{api.Methods("GET")},
|
Middlewares: []core.Middleware{api.Methods("GET")},
|
||||||
},
|
},
|
||||||
"/shortcodes/{shortcode}/delete": {
|
"/shortcodes/{shortcode}/delete": {
|
||||||
Handler: api.HandleDeleteShortcode,
|
Handler: shortcodes.HandleDelete,
|
||||||
Middlewares: []core.Middleware{api.Methods("DELETE"), api.AuthJWT},
|
Middlewares: []core.Middleware{api.Methods("DELETE"), api.AuthJWT},
|
||||||
},
|
},
|
||||||
"/shortcodes/{shortcode}/update": {
|
"/shortcodes/{shortcode}/update": {
|
||||||
Handler: api.HandleUpdateShortcode,
|
Handler: shortcodes.HandleUpdate,
|
||||||
Middlewares: []core.Middleware{api.Methods("PATCH"), api.AuthJWT},
|
Middlewares: []core.Middleware{api.Methods("PATCH"), api.AuthJWT},
|
||||||
},
|
},
|
||||||
|
// "/roles": {
|
||||||
|
// Handler: nil,
|
||||||
|
// Middlewares: []core.Middleware{api.Methods("GET"), api.AuthJWT},
|
||||||
|
// },
|
||||||
|
// "/roles/new": {
|
||||||
|
// Handler: nil,
|
||||||
|
// Middlewares: []core.Middleware{api.Methods("POST"), api.AuthJWT},
|
||||||
|
// },
|
||||||
|
// "/roles/{role_uuid}": {
|
||||||
|
// Handler: nil,
|
||||||
|
// Middlewares: []core.Middleware{api.Methods("GET"), api.AuthJWT},
|
||||||
|
// },
|
||||||
|
// "/roles/{role_uuid}/update": {
|
||||||
|
// Handler: nil,
|
||||||
|
// Middlewares: []core.Middleware{api.Methods("PATCH"), api.AuthJWT},
|
||||||
|
// },
|
||||||
|
// "/roles/{role_uuid}/delete": {
|
||||||
|
// Handler: nil,
|
||||||
|
// Middlewares: []core.Middleware{api.Methods("DELETE"), api.AuthJWT},
|
||||||
|
// },
|
||||||
|
// "/permissions": {
|
||||||
|
// Handler: nil,
|
||||||
|
// Middlewares: []core.Middleware{api.Methods("GET"), api.AuthJWT},
|
||||||
|
// },
|
||||||
|
// "/permissions/new": {
|
||||||
|
// Handler: nil,
|
||||||
|
// Middlewares: []core.Middleware{api.Methods("POST"), api.AuthJWT},
|
||||||
|
// },
|
||||||
|
// "/permissions/{permission_id}": {
|
||||||
|
// Handler: nil,
|
||||||
|
// Middlewares: []core.Middleware{api.Methods("PATCH"), api.AuthJWT},
|
||||||
|
// },
|
||||||
|
// "/permissions/{permission_id}/update": {
|
||||||
|
// Handler: nil,
|
||||||
|
// Middlewares: []core.Middleware{api.Methods("PATCH"), api.AuthJWT},
|
||||||
|
// },
|
||||||
|
// "/permissions/{permission_id}/delete": {
|
||||||
|
// Handler: nil,
|
||||||
|
// Middlewares: []core.Middleware{api.Methods("DELETE"), api.AuthJWT},
|
||||||
|
// },
|
||||||
|
// "/roles/{role_uuid}/permissions/": {
|
||||||
|
// Handler: nil,
|
||||||
|
// Middlewares: []core.Middleware{api.Methods("GET"), api.AuthJWT},
|
||||||
|
// },
|
||||||
|
// "/roles/{role_uuid}/permissions/{permission_id}/add": {
|
||||||
|
// Handler: nil,
|
||||||
|
// Middlewares: []core.Middleware{api.Methods("POST"), api.AuthJWT},
|
||||||
|
// },
|
||||||
|
// "/roles/{role_uuid}/permissions/{permission_id}/remove": {
|
||||||
|
// Handler: nil,
|
||||||
|
// Middlewares: []core.Middleware{api.Methods("POST"), api.AuthJWT},
|
||||||
|
// },
|
||||||
"/contact": {
|
"/contact": {
|
||||||
Handler: api.HandleContact,
|
Handler: api.HandleContact,
|
||||||
Middlewares: []core.Middleware{api.Methods("POST"), CSRFMiddleware},
|
Middlewares: []core.Middleware{api.Methods("POST"), CSRFMiddleware},
|
||||||
@@ -187,7 +227,7 @@ func main() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
fmt.Printf("Serving on port %s\n", port)
|
fmt.Printf("Serving on port %s\n", port)
|
||||||
err = http.ListenAndServe(fmt.Sprintf(":%s", port), Cors(mux))
|
err = http.ListenAndServe(fmt.Sprintf(":%s", port), api.CORS(mux))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Error starting server: %s\n", err)
|
fmt.Printf("Error starting server: %s\n", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user