Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,28 @@
*.so
*.dylib

# Test binary, build with `go test -c`
# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# custom
.env
.vscode
.idea
log

# built server
build
swapdoodle

# logs
log/*

# Dependency directories
vendor/

# Go workspace file
go.work
go.work.sum
36 changes: 36 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# syntax=docker/dockerfile:1

ARG app_dir="/home/go/app"


# * Building the application
FROM golang:1.23-alpine3.20 AS build
ARG app_dir

WORKDIR ${app_dir}

RUN --mount=type=cache,target=/go/pkg/mod/ \
--mount=type=bind,source=go.sum,target=go.sum \
--mount=type=bind,source=go.mod,target=go.mod \
go mod download -x

COPY . .
ARG BUILD_STRING=pretendo.swapdoodle.docker
RUN --mount=type=cache,target=/go/pkg/mod/ \
CGO_ENABLED=0 go build -ldflags "-X 'main.serverBuildString=${BUILD_STRING}'" -v -o ${app_dir}/build/server


# * Running the final application
FROM alpine:3.20 AS final
ARG app_dir
WORKDIR ${app_dir}

RUN addgroup go && adduser -D -G go go

RUN mkdir -p ${app_dir}/log && chown go:go ${app_dir}/log

USER go

COPY --from=build ${app_dir}/build/server ${app_dir}/server

CMD [ "./server" ]
60 changes: 60 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# TODO - Assumes a UNIX-like OS

RED := $(shell tput setaf 1)
BLUE := $(shell tput setaf 4)
CYAN := $(shell tput setaf 14)
ORANGE := $(shell tput setaf 202)
YELLOW := $(shell tput setaf 214)
RESET := $(shell tput sgr0)

ifeq ($(shell which go),)
# TODO - Read contents from .git folder instead?
$(error "$(RED)go command not found. Install go to continue $(BLUE)https://go.dev/doc/install$(RESET)")
endif

ifneq ($(wildcard .git),)
# * .git folder exists, build server build string from repo info
ifeq ($(shell which git),)
# TODO - Read contents from .git folder instead?
$(error "$(RED)git command not found. Install git to continue $(ORANGE)https://git-scm.com/downloads$(RESET)")
endif
$(info "$(CYAN)Building server build string from repository info$(RESET)")
# * Build server build string from repo info
BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
REMOTE_ORIGIN := $(shell git config --get remote.origin.url)

# * Handle multiple origin URL formats
HTTPS_PREFIX_CHECK := $(shell echo $(REMOTE_ORIGIN) | head -c 8)
HTTP_PREFIX_CHECK := $(shell echo $(REMOTE_ORIGIN) | head -c 7)
GIT@_PREFIX_CHECK := $(shell echo $(REMOTE_ORIGIN) | head -c 4)

ifeq ($(HTTPS_PREFIX_CHECK), https://)
REMOTE_PATH := $(shell echo $(REMOTE_ORIGIN) | cut -d/ -f4-)
else ifeq ($(HTTP_PREFIX_CHECK), http://)
REMOTE_PATH := $(shell echo $(REMOTE_ORIGIN) | cut -d/ -f4-)
else ifeq ($(GIT@_PREFIX_CHECK), git@)
REMOTE_PATH := $(shell echo $(REMOTE_ORIGIN) | cut -d: -f2-)
else
REMOTE_PATH := $(shell echo $(REMOTE_ORIGIN) | cut -d/ -f2-)
endif

HASH := $(shell git rev-parse --short HEAD)
SERVER_BUILD := $(BRANCH):$(REMOTE_PATH)@$(HASH)

else
# * .git folder not present, assume downloaded from zip file and just use folder name
$(info "$(CYAN)git repository not found. Building server build string from folder name$(RESET)")
SERVER_BUILD := swapdoodle
endif

# * Final build string
DATE_TIME := $(shell date --iso=seconds)
BUILD_STRING := $(SERVER_BUILD), $(DATE_TIME)

default:
ifeq ($(wildcard .env),)
$(warning "$(YELLOW).env file not found, environment variables may not be populated correctly$(RESET)")
endif
go get -u
go mod tidy
go build -mod=vendor -ldflags "-X 'main.serverBuildString=$(BUILD_STRING)'" -o ./build/swapdoodle
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Swapdoodle replacement server

A HPP server for the _Swapdoodle_ 3DS app.

## Configuration

All configuration options are handled via environment variables

`.env` files are supported

| Name | Description | Required |
| ------------------------------- | ---------------------------------------------- | ----------------------------------- |
| `PN_SD_POSTGRES_URI` | Fully qualified URI to your Postgres server | Yes |
| `PN_SD_HPP_SERVER_PORT` | Port for the HPP server | Yes |
| `PN_SD_GRPC_SERVER_PORT` | Port for the GRPC server | Yes |
| `PN_SD_CONFIG_S3_ENDPOINT` | S3 server endpoint | Yes |
| `PN_SD_CONFIG_S3_ACCESS_KEY` | S3 access key ID | Yes |
| `PN_SD_CONFIG_S3_ACCESS_SECRET` | S3 secret | Yes |
| `PN_SD_CONFIG_S3_BUCKET` | S3 bucket | Yes |
| `PN_SD_CONFIG_GRPC_API_KEY` | API Key | No (in which case it is open) |
| `PN_SD_ACCOUNT_GRPC_HOST` | Host name for your account server gRPC service | Yes |
| `PN_SD_ACCOUNT_GRPC_PORT` | Port for your account server gRPC service | Yes |
| `PN_SD_ACCOUNT_GRPC_API_KEY` | API key for your account server gRPC service | No (Assumed to be an open gRPC API) |
6 changes: 0 additions & 6 deletions database/connect_all.go

This file was deleted.

27 changes: 0 additions & 27 deletions database/connect_mongo.go

This file was deleted.

26 changes: 26 additions & 0 deletions database/datastore/is_object_available.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package datastore_db

import (
"database/sql"

"github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
"github.com/silver-volt4/swapdoodle/database"
"github.com/silver-volt4/swapdoodle/globals"
)

func IsObjectAvailable(dataID types.UInt64) *nex.Error {
var temp int
err := database.Postgres.QueryRow(`SELECT data_id FROM datastore.objects WHERE data_id=$1 AND upload_completed=TRUE AND deleted=FALSE`, dataID).Scan(&temp)
if err != nil {
if err == sql.ErrNoRows {
return nex.NewError(nex.ResultCodes.DataStore.NotFound, "Object not found")
}

globals.Logger.Error(err.Error())
// TODO - Send more specific errors?
return nex.NewError(nex.ResultCodes.DataStore.Unknown, err.Error())
}

return nil
}
34 changes: 34 additions & 0 deletions database/datastore/verify_read_access_by_dataid_and_pid.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package datastore_db

import (
"database/sql"

"github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
datastore_types "github.com/PretendoNetwork/nex-protocols-go/v2/datastore/types"
"github.com/silver-volt4/swapdoodle/database"
"github.com/silver-volt4/swapdoodle/globals"
)

func VerifyReadAccessByDataIdAndPID(requesterPID types.PID, metaInfo datastore_types.DataStoreMetaInfo, objectAccessPassword, requesterAccessPassword types.UInt64) *nex.Error {
nexError := IsObjectAvailable(metaInfo.DataID)
if nexError != nil {
return nexError
}

var t bool
err := database.Postgres.QueryRow(`SELECT 1 FROM datastore.objects WHERE data_id=$1 AND (owner = $2 OR $2 IN (SELECT UNNEST(access_permission_recipients)))`, metaInfo.DataID, requesterPID).Scan(&t)

if err != nil {
if err == sql.ErrNoRows {
return nex.NewError(nex.ResultCodes.DataStore.OperationNotAllowed, "Access denied")
}

globals.Logger.Error(err.Error())

// TODO - Send more specific errors?
return nex.NewError(nex.ResultCodes.DataStore.Unknown, err.Error())
}

return nil
}
25 changes: 0 additions & 25 deletions database/get_nex_account_by_pid.go

This file was deleted.

21 changes: 21 additions & 0 deletions database/postgres.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package database

import (
"database/sql"

_ "github.com/lib/pq"
"github.com/silver-volt4/swapdoodle/globals"
)

var Postgres *sql.DB

func ConnectPostgres(uri string) {
var err error

Postgres, err = sql.Open("postgres", uri)
if err != nil {
globals.Logger.Critical(err.Error())
}

globals.Logger.Success("Connected to Postgres!")
}
47 changes: 47 additions & 0 deletions globals/accounts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package globals

import (
"strconv"

"github.com/PretendoNetwork/nex-go/v2"
"github.com/PretendoNetwork/nex-go/v2/types"
)

var HppServerAccount *nex.Account

func AccountDetailsByPID(pid types.PID) (*nex.Account, *nex.Error) {
if pid.Equals(HppServerAccount.PID) {
return HppServerAccount, nil
}

password, errorCode := PasswordFromPID(pid)
if errorCode != 0 {
return nil, nex.NewError(errorCode, "Failed to get password from PID")
}

account := nex.NewAccount(pid, strconv.Itoa(int(pid)), password)

return account, nil
}

func AccountDetailsByUsername(username string) (*nex.Account, *nex.Error) {
if username == HppServerAccount.Username {
return HppServerAccount, nil
}

pidInt, err := strconv.Atoi(username)
if err != nil {
return nil, nex.NewError(nex.ResultCodes.RendezVous.InvalidUsername, "Invalid username")
}

pid := types.NewPID(uint64(pidInt))

password, errorCode := PasswordFromPID(pid)
if errorCode != 0 {
return nil, nex.NewError(errorCode, "Failed to get password from PID")
}

account := nex.NewAccount(pid, username, password)

return account, nil
}
28 changes: 25 additions & 3 deletions globals/globals.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,31 @@
package globals

import (
"github.com/PretendoNetwork/nex-go"
pb "github.com/PretendoNetwork/grpc/go/account"
"github.com/PretendoNetwork/nex-go/v2"
datastore_common "github.com/PretendoNetwork/nex-protocols-common-go/v2/datastore"
common_globals "github.com/PretendoNetwork/nex-protocols-common-go/v2/globals"
"github.com/PretendoNetwork/plogger-go"
"github.com/minio/minio-go/v7"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
)

var Logger = plogger.NewLogger()
var NEXServer *nex.Server
const HPP_ACCESS_KEY = "76f26496"
const S3_KEY_DATASTORE = "ds"

var MinIOClient *minio.Client

var LibraryVersion = nex.NewLibraryVersion(3, 8, 3)
var Logger *plogger.Logger
var KerberosPassword = "" // randomized in init()
var HppServer *nex.HPPServer
var DatastoreCommon *datastore_common.CommonProtocol
var DatastoreManager *common_globals.DataStoreManager
var GRPCAccountClientConnection *grpc.ClientConn
var GRPCAccountClient pb.AccountClient
var GRPCAccountCommonMetadata metadata.MD
var S3BucketName string
var HPPServerPort int
var GRPCServerPort int
var GRPCApiKey string
Loading