mirror of
https://github.com/PretendoNetwork/friends.git
synced 2026-04-25 23:37:46 -05:00
commit
d079c77ff0
51
.github/workflows/docker.yml
vendored
51
.github/workflows/docker.yml
vendored
|
|
@ -10,7 +10,8 @@ env:
|
|||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
jobs:
|
||||
build-publish:
|
||||
build-publish-amd64:
|
||||
name: Build and Publish Docker Image (amd64)
|
||||
env:
|
||||
SHOULD_PUSH_IMAGE: ${{ (github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev')) || github.event_name == 'workflow_dispatch' }}
|
||||
runs-on: ubuntu-latest
|
||||
|
|
@ -48,7 +49,53 @@ jobs:
|
|||
id: build-and-push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
platforms: linux/amd64
|
||||
push: ${{ env.SHOULD_PUSH_IMAGE }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
build-publish-arm64:
|
||||
name: Build and Publish Docker Image (arm64)
|
||||
env:
|
||||
SHOULD_PUSH_IMAGE: ${{ (github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev')) || github.event_name == 'workflow_dispatch' }}
|
||||
runs-on: ubuntu-24.04-arm
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
steps:
|
||||
- name: Set up QEMU for Docker
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Log into the container registry
|
||||
if: ${{ env.SHOULD_PUSH_IMAGE == 'true' }}
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
tags: |
|
||||
type=raw,value=latest-arm,enable=${{ github.ref == 'refs/heads/master' }}
|
||||
type=raw,value=edge-arm,enable=${{ github.ref == 'refs/heads/dev' }}
|
||||
type=sha,suffix=-arm
|
||||
|
||||
- name: Build and push Docker image
|
||||
id: build-and-push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
platforms: linux/arm64
|
||||
push: ${{ env.SHOULD_PUSH_IMAGE }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ ARG app_dir="/home/go/app"
|
|||
|
||||
|
||||
# * Building the application
|
||||
FROM golang:1.23.6-alpine AS build
|
||||
FROM golang:1.25-alpine3.22 AS build
|
||||
ARG app_dir
|
||||
ARG build_string=pretendo.friends.docker
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ RUN --mount=type=cache,target=/go/pkg/mod/ \
|
|||
|
||||
|
||||
# * Running the final application
|
||||
FROM alpine:3.20 AS final
|
||||
FROM alpine:3.22 AS final
|
||||
ARG app_dir
|
||||
WORKDIR ${app_dir}
|
||||
|
||||
|
|
|
|||
27
README.md
27
README.md
|
|
@ -84,15 +84,18 @@ All configuration options are handled via environment variables
|
|||
|
||||
`.env` files are supported
|
||||
|
||||
| Name | Description | Required |
|
||||
|---------------------------------------------|------------------------------------------------------------------------------------------------------------------------|-------------------------------------|
|
||||
| `PN_FRIENDS_CONFIG_DATABASE_URI` | Fully qualified URI to your Postgres server (Example `postgres://username:password@localhost/friends?sslmode=disable`) | Yes |
|
||||
| `PN_FRIENDS_CONFIG_AES_KEY` | AES key used in tokens provided by the account server | Yes |
|
||||
| `PN_FRIENDS_CONFIG_GRPC_API_KEY` | API key for your GRPC server | No (Assumed to be an open gRPC API) |
|
||||
| `PN_FRIENDS_GRPC_SERVER_PORT` | Port for the GRPC server | Yes |
|
||||
| `PN_FRIENDS_AUTHENTICATION_SERVER_PORT` | Port for the authentication server | Yes |
|
||||
| `PN_FRIENDS_SECURE_SERVER_HOST` | Host name for the secure server (should point to the same address as the authentication server) | Yes |
|
||||
| `PN_FRIENDS_SECURE_SERVER_PORT` | Port for the secure server | Yes |
|
||||
| `PN_FRIENDS_ACCOUNT_GRPC_HOST` | Host name for your account server gRPC service | Yes |
|
||||
| `PN_FRIENDS_ACCOUNT_GRPC_PORT` | Port for your account server gRPC service | Yes |
|
||||
| `PN_FRIENDS_ACCOUNT_GRPC_API_KEY` | API key for your account server gRPC service | No (Assumed to be an open gRPC API) |
|
||||
| Name | Description | Required |
|
||||
| ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ----------------------------------- |
|
||||
| `PN_FRIENDS_CONFIG_POSTGRES_URI` | Fully qualified URI to your Postgres server (Example `postgres://username:password@localhost/friends?sslmode=disable`) | Yes |
|
||||
| `PN_FRIENDS_CONFIG_POSTGRES_MAX_CONNECTIONS` | Postgres server max connections | Yes |
|
||||
| `PN_FRIENDS_CONFIG_AES_KEY` | AES key used in tokens provided by the account server | Yes |
|
||||
| `PN_FRIENDS_CONFIG_GRPC_API_KEY` | API key for your GRPC server | No (Assumed to be an open gRPC API) |
|
||||
| `PN_FRIENDS_CONFIG_GRPC_SERVER_PORT` | Port for the GRPC server | Yes |
|
||||
| `PN_FRIENDS_CONFIG_AUTHENTICATION_SERVER_PORT` | Port for the authentication server | Yes |
|
||||
| `PN_FRIENDS_CONFIG_SECURE_SERVER_HOST` | Host name for the secure server (should point to the same address as the authentication server) | Yes |
|
||||
| `PN_FRIENDS_CONFIG_SECURE_SERVER_PORT` | Port for the secure server | Yes |
|
||||
| `PN_FRIENDS_CONFIG_ACCOUNT_GRPC_HOST` | Host name for your account server gRPC service | Yes |
|
||||
| `PN_FRIENDS_CONFIG_ACCOUNT_GRPC_PORT` | Port for your account server gRPC service | Yes |
|
||||
| `PN_FRIENDS_CONFIG_ACCOUNT_GRPC_API_KEY` | API key for your account server gRPC service | No (Assumed to be an open gRPC API) |
|
||||
| `PN_FRIENDS_CONFIG_HEALTH_CHECK_PORT` | Port for the basic UDP health check server | No |
|
||||
| `PN_FRIENDS_CONFIG_ENABLE_BELLA` | Enables a debug user named "Bella" which is always assigned as your friend | No | No
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
package database
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
_ "github.com/lib/pq"
|
||||
|
||||
"github.com/PretendoNetwork/friends/globals"
|
||||
|
|
@ -14,7 +12,7 @@ var Manager *sqlmanager.SQLManager
|
|||
func ConnectPostgres() {
|
||||
var err error
|
||||
|
||||
Manager, err = sqlmanager.NewSQLManager("postgres", os.Getenv("PN_FRIENDS_CONFIG_DATABASE_URI"), int64(globals.DatabaseMaxConnections))
|
||||
Manager, err = sqlmanager.NewSQLManager("postgres", globals.Config.PostgresURI, globals.Config.PostgresMaxConnections)
|
||||
if err != nil {
|
||||
globals.Logger.Critical(err.Error())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import (
|
|||
"context"
|
||||
"strconv"
|
||||
|
||||
pb "github.com/PretendoNetwork/grpc-go/account"
|
||||
pb "github.com/PretendoNetwork/grpc/go/account/v2"
|
||||
"github.com/PretendoNetwork/nex-go/v2"
|
||||
"github.com/PretendoNetwork/nex-go/v2/types"
|
||||
"google.golang.org/grpc/metadata"
|
||||
|
|
@ -32,7 +32,7 @@ func AccountDetailsByPID(pid types.PID) (*nex.Account, *nex.Error) {
|
|||
}
|
||||
|
||||
username := strconv.Itoa(int(pid))
|
||||
account := nex.NewAccount(pid, username, response.Password)
|
||||
account := nex.NewAccount(pid, username, response.Password, false)
|
||||
|
||||
return account, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import (
|
|||
"fmt"
|
||||
"strconv"
|
||||
|
||||
pb "github.com/PretendoNetwork/grpc-go/account"
|
||||
pb "github.com/PretendoNetwork/grpc/go/account/v2"
|
||||
"github.com/PretendoNetwork/nex-go/v2"
|
||||
"github.com/PretendoNetwork/nex-go/v2/types"
|
||||
"google.golang.org/grpc/metadata"
|
||||
|
|
@ -44,7 +44,7 @@ func AccountDetailsByUsername(username string) (*nex.Account, *nex.Error) {
|
|||
return nil, nex.NewError(nex.ResultCodes.RendezVous.InvalidPID, "Invalid PID")
|
||||
}
|
||||
|
||||
account := nex.NewAccount(types.NewPID(uint64(pid)), username, response.Password)
|
||||
account := nex.NewAccount(types.NewPID(uint64(pid)), username, response.Password, false)
|
||||
|
||||
return account, nil
|
||||
}
|
||||
|
|
|
|||
19
globals/config.go
Normal file
19
globals/config.go
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
package globals
|
||||
|
||||
type config struct {
|
||||
PostgresURI string
|
||||
PostgresMaxConnections int64
|
||||
AESKey string
|
||||
GRPCAPIKey string `envconf:"optional"`
|
||||
GRPCServerPort uint16
|
||||
AuthenticationServerPort uint16
|
||||
SecureServerHost string
|
||||
SecureServerPort uint16
|
||||
AccountGRPCHost string
|
||||
AccountGRPCPort uint16
|
||||
AccountGRPCAPIKey string `envconf:"optional"`
|
||||
HealthCheckPort uint16 `envconf:"optional"`
|
||||
EnableBella bool `envconf:"optional"`
|
||||
}
|
||||
|
||||
var Config *config = &config{}
|
||||
308
globals/config_parser.go
Normal file
308
globals/config_parser.go
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
package globals
|
||||
|
||||
// * NOTE: THIS IS ALL LIBRARY CODE, INTENDED TO BE REMOVED FROM THIS REPO IN THE FUTURE.
|
||||
// * THIS IS ONLY HERE FOR NOW SO I CAN PLAY AROUND WITH THE IDEA.
|
||||
|
||||
// * MESSING AROUND WITH THIS BECAUSE I DIDN'T REALLY LIKE THE WAY EXISTING CONFIG
|
||||
// * PARSERS WORKED, THEY ALL HAD WEIRD QUIRKS LIKE ODD SEMANTICS FOR STRUCT TAGS,
|
||||
// * COULDN'T HANDLE COMPLEX SLICES AND MAPS CLEANLY, ETC.
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type fieldTagOptions struct {
|
||||
optional bool
|
||||
defaultValue string
|
||||
hasDefault bool
|
||||
envNameOverride string
|
||||
}
|
||||
|
||||
func parseFieldTag(tag string) fieldTagOptions {
|
||||
options := fieldTagOptions{}
|
||||
if tag == "" {
|
||||
return options
|
||||
}
|
||||
|
||||
if i := strings.Index(tag, "default:"); i != -1 {
|
||||
options.defaultValue = tag[i+8:]
|
||||
options.hasDefault = true
|
||||
tag = strings.TrimSuffix(tag[:i], ",")
|
||||
}
|
||||
|
||||
for _, part := range strings.Split(tag, ",") {
|
||||
part = strings.TrimSpace(part)
|
||||
if part == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if part == "optional" {
|
||||
options.optional = true
|
||||
} else if strings.HasPrefix(part, "env:") {
|
||||
options.envNameOverride = strings.TrimPrefix(part, "env:")
|
||||
}
|
||||
}
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
type ConfigParser[T any] struct {
|
||||
config T
|
||||
prefix string
|
||||
initialisms map[string]bool
|
||||
allowedPluralInitialisms map[string]bool
|
||||
}
|
||||
|
||||
func (cp *ConfigParser[T]) toPascalCase(str string) string {
|
||||
lowercase := strings.ToLower(str)
|
||||
words := strings.Split(lowercase, "_")
|
||||
|
||||
var pascalCase strings.Builder
|
||||
|
||||
for _, word := range words {
|
||||
pascalCase.WriteString(cp.capitalizeWord(word))
|
||||
}
|
||||
|
||||
return pascalCase.String()
|
||||
}
|
||||
|
||||
func (cp *ConfigParser[T]) capitalizeWord(word string) string {
|
||||
if word == "" {
|
||||
return word
|
||||
}
|
||||
|
||||
upper := strings.ToUpper(word)
|
||||
|
||||
if cp.initialisms[upper] {
|
||||
return upper
|
||||
}
|
||||
|
||||
endsWithS := strings.HasSuffix(upper, "S")
|
||||
withoutS := strings.TrimSuffix(upper, "S")
|
||||
|
||||
if cp.initialisms[withoutS] && endsWithS && cp.allowedPluralInitialisms[withoutS] {
|
||||
return withoutS + "s"
|
||||
} else if cp.initialisms[withoutS] {
|
||||
return upper
|
||||
}
|
||||
|
||||
r, n := utf8.DecodeRuneInString(word)
|
||||
if r == utf8.RuneError && n == 0 {
|
||||
return word
|
||||
}
|
||||
|
||||
return string(unicode.ToUpper(r)) + word[n:]
|
||||
}
|
||||
|
||||
func (cp *ConfigParser[T]) toEnvVarName(fieldName string) string {
|
||||
var result strings.Builder
|
||||
if cp.prefix != "" {
|
||||
result.WriteString(cp.prefix)
|
||||
}
|
||||
|
||||
runes := []rune(fieldName)
|
||||
for i := 0; i < len(runes); i++ {
|
||||
r := runes[i]
|
||||
|
||||
if r == 's' && i > 0 && unicode.IsUpper(runes[i-1]) {
|
||||
result.WriteRune('S')
|
||||
continue
|
||||
}
|
||||
|
||||
if i > 0 && unicode.IsUpper(r) {
|
||||
prevIsLower := unicode.IsLower(runes[i-1])
|
||||
nextIsLower := i+1 < len(runes) && unicode.IsLower(runes[i+1])
|
||||
nextIsPluralS := i+1 < len(runes) && runes[i+1] == 's' && (i+2 >= len(runes) || unicode.IsUpper(runes[i+2]))
|
||||
|
||||
if prevIsLower || (nextIsLower && !nextIsPluralS) {
|
||||
result.WriteRune('_')
|
||||
}
|
||||
}
|
||||
|
||||
result.WriteRune(unicode.ToUpper(r))
|
||||
}
|
||||
|
||||
return result.String()
|
||||
}
|
||||
|
||||
func (cp *ConfigParser[T]) SetPrefix(prefix string) *ConfigParser[T] {
|
||||
cp.prefix = prefix + "_"
|
||||
|
||||
return cp
|
||||
}
|
||||
|
||||
func (cp *ConfigParser[T]) AddInitialisms(initialisms map[string]bool) *ConfigParser[T] {
|
||||
for key, value := range initialisms {
|
||||
cp.initialisms[key] = value
|
||||
}
|
||||
|
||||
return cp
|
||||
}
|
||||
|
||||
func (cp *ConfigParser[T]) ParseFromEnv() T {
|
||||
envAsPascal := make(map[string]string)
|
||||
|
||||
for _, env := range os.Environ() {
|
||||
pair := strings.SplitN(env, "=", 2)
|
||||
key := pair[0]
|
||||
value := strings.TrimSpace(pair[1])
|
||||
|
||||
if !strings.HasPrefix(key, cp.prefix) {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldName := cp.toPascalCase(strings.TrimPrefix(key, cp.prefix))
|
||||
|
||||
envAsPascal[fieldName] = value
|
||||
}
|
||||
|
||||
v := reflect.ValueOf(cp.config).Elem()
|
||||
t := v.Type()
|
||||
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
fieldName := field.Name
|
||||
fieldValue := v.Field(i)
|
||||
fieldOptions := parseFieldTag(field.Tag.Get("envconf"))
|
||||
errors := make([]string, 0)
|
||||
warnings := make([]string, 0)
|
||||
|
||||
envVarName := cp.toEnvVarName(fieldName)
|
||||
envValue, exists := envAsPascal[fieldName]
|
||||
|
||||
if fieldOptions.envNameOverride != "" {
|
||||
envVarName = fieldOptions.envNameOverride
|
||||
envValue, exists = os.LookupEnv(envVarName)
|
||||
}
|
||||
|
||||
if !exists && fieldOptions.hasDefault {
|
||||
envValue = fieldOptions.defaultValue
|
||||
exists = true
|
||||
|
||||
warnings = append(warnings, fmt.Sprintf("Optional field %s does not have a corresponding %s environment variable. Using default value \"%s\"", fieldName, envVarName, envValue))
|
||||
}
|
||||
|
||||
if exists && fieldValue.CanSet() {
|
||||
fieldType := fieldValue.Type()
|
||||
switch fieldValue.Kind() {
|
||||
case reflect.String:
|
||||
fieldValue.SetString(envValue)
|
||||
case reflect.Bool:
|
||||
if boolVal, err := strconv.ParseBool(envValue); err == nil {
|
||||
fieldValue.SetBool(boolVal)
|
||||
}
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
if intVal, err := strconv.ParseInt(envValue, 10, fieldValue.Type().Bits()); err == nil {
|
||||
fieldValue.SetInt(intVal)
|
||||
} else {
|
||||
errors = append(errors, fmt.Sprintf("Error parsing %s: %v", envVarName, err))
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
if uintVal, err := strconv.ParseUint(envValue, 10, fieldValue.Type().Bits()); err == nil {
|
||||
fieldValue.SetUint(uintVal)
|
||||
} else {
|
||||
errors = append(errors, fmt.Sprintf("Error parsing %s: %v", envVarName, err))
|
||||
}
|
||||
case reflect.Float32, reflect.Float64:
|
||||
if floatVal, err := strconv.ParseFloat(envValue, fieldValue.Type().Bits()); err == nil {
|
||||
fieldValue.SetFloat(floatVal)
|
||||
} else {
|
||||
errors = append(errors, fmt.Sprintf("Error parsing %s: %v", envVarName, err))
|
||||
}
|
||||
case reflect.Slice, reflect.Map:
|
||||
sliceOrMap := reflect.New(fieldType)
|
||||
if err := json.Unmarshal([]byte(envValue), sliceOrMap.Interface()); err != nil {
|
||||
errors = append(errors, fmt.Sprintf("Error parsing %s: %v", envVarName, err))
|
||||
}
|
||||
fieldValue.Set(sliceOrMap.Elem())
|
||||
}
|
||||
} else if !exists {
|
||||
if !fieldOptions.optional {
|
||||
errors = append(errors, fmt.Sprintf("Required field %s does not have a corresponding %s environment variable", fieldName, envVarName))
|
||||
} else if !fieldOptions.hasDefault {
|
||||
warnings = append(warnings, fmt.Sprintf("Optional field %s does not have a corresponding %s environment variable and no default value. Skipping", fieldName, envVarName))
|
||||
}
|
||||
}
|
||||
|
||||
if len(warnings) != 0 {
|
||||
for _, warning := range warnings {
|
||||
fmt.Println(warning)
|
||||
}
|
||||
}
|
||||
|
||||
if len(errors) != 0 {
|
||||
for _, err := range errors {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
return cp.config
|
||||
}
|
||||
|
||||
func NewConfigParser[T any](config T) *ConfigParser[T] {
|
||||
return &ConfigParser[T]{
|
||||
config: config,
|
||||
initialisms: map[string]bool{ // * https://go.googlesource.com/lint/+/818c5a804067/lint.go#767
|
||||
"ACL": true,
|
||||
"API": true,
|
||||
"ASCII": true,
|
||||
"CPU": true,
|
||||
"CSS": true,
|
||||
"DNS": true,
|
||||
"EOF": true,
|
||||
"GUID": true,
|
||||
"HTML": true,
|
||||
"HTTP": true,
|
||||
"HTTPS": true,
|
||||
"ID": true,
|
||||
"IP": true,
|
||||
"JSON": true,
|
||||
"LHS": true,
|
||||
"QPS": true,
|
||||
"RAM": true,
|
||||
"RHS": true,
|
||||
"RPC": true,
|
||||
"SLA": true,
|
||||
"SMTP": true,
|
||||
"SQL": true,
|
||||
"SSH": true,
|
||||
"TCP": true,
|
||||
"TLS": true,
|
||||
"TTL": true,
|
||||
"UDP": true,
|
||||
"UI": true,
|
||||
"UID": true,
|
||||
"UUID": true,
|
||||
"URI": true,
|
||||
"URL": true,
|
||||
"UTF8": true,
|
||||
"VM": true,
|
||||
"XML": true,
|
||||
"XMPP": true,
|
||||
"XSRF": true,
|
||||
"XSS": true,
|
||||
"NEX": true, // * Start of our custom ones
|
||||
"GRPC": true,
|
||||
"AES": true,
|
||||
},
|
||||
allowedPluralInitialisms: map[string]bool{
|
||||
"API": true,
|
||||
"GUID": true,
|
||||
"ID": true,
|
||||
"IP": true,
|
||||
"UUID": true,
|
||||
"URI": true,
|
||||
"URL": true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ package globals
|
|||
import (
|
||||
"context"
|
||||
|
||||
pb "github.com/PretendoNetwork/grpc-go/account"
|
||||
pb "github.com/PretendoNetwork/grpc/go/account/v2"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package globals
|
|||
|
||||
import (
|
||||
"github.com/PretendoNetwork/friends/types"
|
||||
pb "github.com/PretendoNetwork/grpc-go/account"
|
||||
pb "github.com/PretendoNetwork/grpc/go/account/v2"
|
||||
"github.com/PretendoNetwork/nex-go/v2"
|
||||
"github.com/PretendoNetwork/plogger-go"
|
||||
"google.golang.org/grpc"
|
||||
|
|
@ -21,6 +21,5 @@ var SecureEndpoint *nex.PRUDPEndPoint
|
|||
var ConnectedUsers *nex.MutexMap[uint32, *types.ConnectedUser]
|
||||
var AESKey []byte
|
||||
var GRPCAccountClientConnection *grpc.ClientConn
|
||||
var GRPCAccountClient pb.AccountClient
|
||||
var GRPCAccountClient pb.AccountServiceClient
|
||||
var GRPCAccountCommonMetadata metadata.MD
|
||||
var DatabaseMaxConnections int
|
||||
|
|
|
|||
48
go.mod
48
go.mod
|
|
@ -1,41 +1,47 @@
|
|||
module github.com/PretendoNetwork/friends
|
||||
|
||||
go 1.23.0
|
||||
go 1.24.0
|
||||
|
||||
toolchain go1.23.6
|
||||
toolchain go1.24.3
|
||||
|
||||
require (
|
||||
github.com/PretendoNetwork/grpc-go v1.0.2
|
||||
github.com/PretendoNetwork/nex-go/v2 v2.1.2
|
||||
github.com/PretendoNetwork/nex-protocols-common-go/v2 v2.2.2
|
||||
github.com/PretendoNetwork/nex-protocols-go/v2 v2.2.1
|
||||
github.com/PretendoNetwork/plogger-go v1.0.4
|
||||
github.com/PretendoNetwork/grpc/go v0.0.0-20260114221322-0631a1e0c840
|
||||
github.com/PretendoNetwork/nex-go/v2 v2.3.0
|
||||
github.com/PretendoNetwork/nex-protocols-common-go/v2 v2.4.0
|
||||
github.com/PretendoNetwork/nex-protocols-go/v2 v2.2.2
|
||||
github.com/PretendoNetwork/plogger-go v1.1.0
|
||||
github.com/PretendoNetwork/sql-manager v1.0.0
|
||||
github.com/golang/protobuf v1.5.4
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/lib/pq v1.10.9
|
||||
google.golang.org/grpc v1.70.0
|
||||
google.golang.org/grpc v1.78.0
|
||||
)
|
||||
|
||||
replace google.golang.org/genproto => google.golang.org/genproto v0.0.0-20240520151616-dc85e6b867a5
|
||||
|
||||
require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/dolthub/maphash v0.1.0 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/jwalton/go-supportscolor v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
github.com/lxzan/gws v1.8.8 // indirect
|
||||
github.com/klauspost/compress v1.18.3 // indirect
|
||||
github.com/lxzan/gws v1.8.9 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.67.5 // indirect
|
||||
github.com/prometheus/procfs v0.19.2 // indirect
|
||||
github.com/rasky/go-lzo v0.0.0-20200203143853-96a758eda86e // indirect
|
||||
github.com/superwhiskers/crunch/v3 v3.5.7 // indirect
|
||||
golang.org/x/exp v0.0.0-20250215185904-eff6e970281f // indirect
|
||||
golang.org/x/mod v0.23.0 // indirect
|
||||
golang.org/x/net v0.35.0 // indirect
|
||||
golang.org/x/sync v0.11.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/term v0.29.0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b // indirect
|
||||
google.golang.org/protobuf v1.36.5 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
golang.org/x/exp v0.0.0-20260112195511-716be5621a96 // indirect
|
||||
golang.org/x/mod v0.32.0 // indirect
|
||||
golang.org/x/net v0.49.0 // indirect
|
||||
golang.org/x/sync v0.19.0 // indirect
|
||||
golang.org/x/sys v0.40.0 // indirect
|
||||
golang.org/x/term v0.39.0 // indirect
|
||||
golang.org/x/text v0.33.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260114163908-3f89685c29c3 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
)
|
||||
|
|
|
|||
133
go.sum
133
go.sum
|
|
@ -1,86 +1,119 @@
|
|||
github.com/PretendoNetwork/grpc-go v1.0.2 h1:9TvKmX7dCOANyoHEra1MMYqS1N/RGav66TRG4SHInvo=
|
||||
github.com/PretendoNetwork/grpc-go v1.0.2/go.mod h1:XZjEsij9lL7HJBNkH6JPbBIkUSq/1rjflvjGdv+DAj0=
|
||||
github.com/PretendoNetwork/nex-go/v2 v2.1.2 h1:OJFAS6U6VNzZ4YzteKqUEZ5aJMwWIHODeRrLwNbN7nw=
|
||||
github.com/PretendoNetwork/nex-go/v2 v2.1.2/go.mod h1:3LyJzsv3AataJW8D0binp15Q8ZH22MWTYly1VNtXi64=
|
||||
github.com/PretendoNetwork/nex-protocols-common-go/v2 v2.2.2 h1:rBJNZDJ92pa9fU3Og0sanyizJTWnELPoGR0Tjz8zlws=
|
||||
github.com/PretendoNetwork/nex-protocols-common-go/v2 v2.2.2/go.mod h1:iuNMuBK/zww+44d6ajfLsOusXx/6Llj3zSkmhJwMuuM=
|
||||
github.com/PretendoNetwork/nex-protocols-go/v2 v2.2.1 h1:/dsuP0W7bZNvrXoXH0ZRdxpxonfbWmmson51WCQdpEQ=
|
||||
github.com/PretendoNetwork/nex-protocols-go/v2 v2.2.1/go.mod h1:+soBHmwX6ixGxj6cphLuCvfJqxcZPuowc/5e7Qi9Bz0=
|
||||
github.com/PretendoNetwork/plogger-go v1.0.4 h1:PF7xHw9eDRHH+RsAP9tmAE7fG0N0p6H4iPwHKnsoXwc=
|
||||
github.com/PretendoNetwork/plogger-go v1.0.4/go.mod h1:7kD6M4vPq1JL4LTuPg6kuB1OvUBOwQOtAvTaUwMbwvU=
|
||||
github.com/PretendoNetwork/grpc/go v0.0.0-20260114221322-0631a1e0c840 h1:IkflRrU2XT/8voysYxZTxcQYPyMBCt7yBHWy8U6Q/tU=
|
||||
github.com/PretendoNetwork/grpc/go v0.0.0-20260114221322-0631a1e0c840/go.mod h1:L6We4KkcQeiQVPrF7iu8Zax0B1Bm0v4nssR1JOAiRFQ=
|
||||
github.com/PretendoNetwork/nex-go/v2 v2.3.0 h1:CQNm/DzYhXvyzD/5l+Dxfp0/AbObuCfyfhLAeY6BejI=
|
||||
github.com/PretendoNetwork/nex-go/v2 v2.3.0/go.mod h1:2xKxiTtNxGliQ80xeicc6w3D53hmunOndoB3XJxUn/8=
|
||||
github.com/PretendoNetwork/nex-protocols-common-go/v2 v2.4.0 h1:EhXj1EDbNgdg40BPx/7n1HHsAy/DayGIWthu81UNyvI=
|
||||
github.com/PretendoNetwork/nex-protocols-common-go/v2 v2.4.0/go.mod h1:tNtZly5sL3wfy4LVgybS2efm00L/wNgyvcrBV59S/YM=
|
||||
github.com/PretendoNetwork/nex-protocols-go/v2 v2.2.2 h1:RNXr0jTZZYZOZTch1e18cbx6BFfIT2IoFR9bnLd/6Ig=
|
||||
github.com/PretendoNetwork/nex-protocols-go/v2 v2.2.2/go.mod h1:+soBHmwX6ixGxj6cphLuCvfJqxcZPuowc/5e7Qi9Bz0=
|
||||
github.com/PretendoNetwork/plogger-go v1.1.0 h1:x2XgyeeM8zDFGy+NcIZd3SYC2fNrVWpBBbkqTejOfiM=
|
||||
github.com/PretendoNetwork/plogger-go v1.1.0/go.mod h1:wpltahp91IXr9nOvWgwep8zGtUKDeCVwm+/Wa484lQ4=
|
||||
github.com/PretendoNetwork/sql-manager v1.0.0 h1:g0SYpQgi6Kk4ptufrLTSmDxvqaYioTcfXaDH+uXC+a0=
|
||||
github.com/PretendoNetwork/sql-manager v1.0.0/go.mod h1:NaEdDC0S/9J8eoxCDvuHB8fofv0svh44lWvgCdtuMq0=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
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/dolthub/maphash v0.1.0 h1:bsQ7JsF4FkkWyrP3oCnFJgrCUAFbFf3kOl4L/QxPDyQ=
|
||||
github.com/dolthub/maphash v0.1.0/go.mod h1:gkg4Ch4CdCDu5h6PMriVLawB7koZ+5ijb9puGMV50a4=
|
||||
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
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/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/jwalton/go-supportscolor v1.2.0 h1:g6Ha4u7Vm3LIsQ5wmeBpS4gazu0UP1DRDE8y6bre4H8=
|
||||
github.com/jwalton/go-supportscolor v1.2.0/go.mod h1:hFVUAZV2cWg+WFFC4v8pT2X/S2qUUBYMioBD9AINXGs=
|
||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw=
|
||||
github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lxzan/gws v1.8.8 h1:st193ZG8qN8sSw8/g/UituFhs7etmKzS7jUqhijg5wM=
|
||||
github.com/lxzan/gws v1.8.8/go.mod h1:FcGeRMB7HwGuTvMLR24ku0Zx0p6RXqeKASeMc4VYgi4=
|
||||
github.com/lxzan/gws v1.8.9 h1:VU3SGUeWlQrEwfUSfokcZep8mdg/BrUF+y73YYshdBM=
|
||||
github.com/lxzan/gws v1.8.9/go.mod h1:d9yHaR1eDTBHagQC6KY7ycUOaz5KWeqQtP3xu7aMK8Y=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
|
||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4=
|
||||
github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw=
|
||||
github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws=
|
||||
github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw=
|
||||
github.com/rasky/go-lzo v0.0.0-20200203143853-96a758eda86e h1:dCWirM5F3wMY+cmRda/B1BiPsFtmzXqV9b0hLWtVBMs=
|
||||
github.com/rasky/go-lzo v0.0.0-20200203143853-96a758eda86e/go.mod h1:9leZcVcItj6m9/CfHY5Em/iBrCz7js8LcRQGTKEEv2M=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/superwhiskers/crunch/v3 v3.5.7 h1:N9RLxaR65C36i26BUIpzPXGy2f6pQ7wisu2bawbKNqg=
|
||||
github.com/superwhiskers/crunch/v3 v3.5.7/go.mod h1:4ub2EKgF1MAhTjoOCTU4b9uLMsAweHEa89aRrfAypXA=
|
||||
go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
|
||||
go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
|
||||
go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
|
||||
go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
|
||||
go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4=
|
||||
go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
|
||||
go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
|
||||
go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
|
||||
golang.org/x/exp v0.0.0-20250215185904-eff6e970281f h1:oFMYAjX0867ZD2jcNiLBrI9BdpmEkvPyi5YrBGXbamg=
|
||||
golang.org/x/exp v0.0.0-20250215185904-eff6e970281f/go.mod h1:BHOTPb3L19zxehTsLoJXVaTktb06DFgmdW6Wb9s8jqk=
|
||||
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
|
||||
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
|
||||
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
|
||||
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
|
||||
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
|
||||
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
|
||||
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||
golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU=
|
||||
golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU=
|
||||
golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
|
||||
golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
|
||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
|
||||
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU=
|
||||
golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s=
|
||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b h1:FQtJ1MxbXoIIrZHZ33M+w5+dAP9o86rgpjoKr/ZmT7k=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250212204824-5a70512c5d8b/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
|
||||
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
|
||||
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
|
||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY=
|
||||
golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww=
|
||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260114163908-3f89685c29c3 h1:C4WAdL+FbjnGlpp2S+HMVhBeCq2Lcib4xZqfPNF6OoQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260114163908-3f89685c29c3/go.mod h1:j9x/tPzZkyxcgEFkiKEEGxfvyumM01BEtsW8xzOahRQ=
|
||||
google.golang.org/grpc v1.78.0 h1:K1XZG/yGDJnzMdd/uZHAkVqJE+xIDOcmdSFZkBUicNc=
|
||||
google.golang.org/grpc v1.78.0/go.mod h1:I47qjTo4OKbMkjA/aOOwxDIiPSBofUtQUI5EfpWvW7U=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/PretendoNetwork/friends/database"
|
||||
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
|
||||
"github.com/PretendoNetwork/friends/globals"
|
||||
pb "github.com/PretendoNetwork/grpc-go/friends"
|
||||
pb "github.com/PretendoNetwork/grpc/go/friends"
|
||||
)
|
||||
|
||||
func (s *gRPCFriendsServer) AcceptFriendRequest(ctx context.Context, in *pb.AcceptFriendRequestRequest) (*pb.AcceptFriendRequestResponse, error) {
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ package grpc
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os"
|
||||
|
||||
"github.com/PretendoNetwork/friends/globals"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/metadata"
|
||||
)
|
||||
|
|
@ -15,7 +15,7 @@ func apiKeyInterceptor(ctx context.Context, req interface{}, info *grpc.UnarySer
|
|||
if ok {
|
||||
apiKeyHeader := md.Get("X-API-Key")
|
||||
|
||||
if len(apiKeyHeader) == 0 || apiKeyHeader[0] != os.Getenv("PN_FRIENDS_CONFIG_GRPC_API_KEY") {
|
||||
if len(apiKeyHeader) == 0 || apiKeyHeader[0] != globals.Config.GRPCAPIKey {
|
||||
return nil, errors.New("Missing or invalid API key")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/PretendoNetwork/friends/database"
|
||||
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
|
||||
"github.com/PretendoNetwork/friends/globals"
|
||||
pb "github.com/PretendoNetwork/grpc-go/friends"
|
||||
pb "github.com/PretendoNetwork/grpc/go/friends"
|
||||
)
|
||||
|
||||
func (s *gRPCFriendsServer) DenyFriendRequest(ctx context.Context, in *pb.DenyFriendRequestRequest) (*pb.DenyFriendRequestResponse, error) {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import (
|
|||
database_3ds "github.com/PretendoNetwork/friends/database/3ds"
|
||||
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
|
||||
"github.com/PretendoNetwork/friends/globals"
|
||||
pb "github.com/PretendoNetwork/grpc-go/friends"
|
||||
pb "github.com/PretendoNetwork/grpc/go/friends"
|
||||
)
|
||||
|
||||
func (s *gRPCFriendsServer) GetUserFriendPIDs(ctx context.Context, in *pb.GetUserFriendPIDsRequest) (*pb.GetUserFriendPIDsResponse, error) {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/PretendoNetwork/friends/database"
|
||||
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
|
||||
"github.com/PretendoNetwork/friends/globals"
|
||||
pb "github.com/PretendoNetwork/grpc-go/friends"
|
||||
pb "github.com/PretendoNetwork/grpc/go/friends"
|
||||
)
|
||||
|
||||
func (s *gRPCFriendsServer) GetUserFriendRequestsIncoming(ctx context.Context, in *pb.GetUserFriendRequestsIncomingRequest) (*pb.GetUserFriendRequestsIncomingResponse, error) {
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
pb "github.com/PretendoNetwork/grpc-go/friends"
|
||||
"github.com/PretendoNetwork/friends/globals"
|
||||
pb "github.com/PretendoNetwork/grpc/go/friends"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
|
|
@ -15,7 +15,7 @@ type gRPCFriendsServer struct {
|
|||
}
|
||||
|
||||
func StartGRPCServer() {
|
||||
listener, err := net.Listen("tcp", fmt.Sprintf(":%s", os.Getenv("PN_FRIENDS_GRPC_SERVER_PORT")))
|
||||
listener, err := net.Listen("tcp", fmt.Sprintf(":%d", globals.Config.GRPCServerPort))
|
||||
if err != nil {
|
||||
log.Fatalf("failed to listen: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import (
|
|||
|
||||
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
|
||||
"github.com/PretendoNetwork/friends/globals"
|
||||
pb "github.com/PretendoNetwork/grpc-go/friends"
|
||||
pb "github.com/PretendoNetwork/grpc/go/friends"
|
||||
"github.com/PretendoNetwork/nex-go/v2/types"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import (
|
|||
"context"
|
||||
|
||||
"github.com/PretendoNetwork/friends/globals"
|
||||
pb "github.com/PretendoNetwork/grpc-go/friends"
|
||||
pb "github.com/PretendoNetwork/grpc/go/friends"
|
||||
nex "github.com/PretendoNetwork/nex-go/v2"
|
||||
"github.com/PretendoNetwork/nex-go/v2/constants"
|
||||
nintendo_notifications "github.com/PretendoNetwork/nex-protocols-go/v2/nintendo-notifications"
|
||||
|
|
|
|||
123
init.go
123
init.go
|
|
@ -1,18 +1,16 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/PretendoNetwork/friends/database"
|
||||
"github.com/PretendoNetwork/friends/globals"
|
||||
"github.com/PretendoNetwork/friends/types"
|
||||
pb "github.com/PretendoNetwork/grpc-go/account"
|
||||
pb "github.com/PretendoNetwork/grpc/go/account/v2"
|
||||
"github.com/PretendoNetwork/nex-go/v2"
|
||||
nex_types "github.com/PretendoNetwork/nex-go/v2/types"
|
||||
"github.com/PretendoNetwork/plogger-go"
|
||||
|
|
@ -27,7 +25,6 @@ func init() {
|
|||
globals.Logger = plogger.NewLogger()
|
||||
globals.ConnectedUsers = nex.NewMutexMap[uint32, *types.ConnectedUser]()
|
||||
|
||||
// * Setup RSA private key for token parsing
|
||||
var err error
|
||||
|
||||
err = godotenv.Load()
|
||||
|
|
@ -35,31 +32,7 @@ func init() {
|
|||
globals.Logger.Warningf("Error loading .env file: %s", err.Error())
|
||||
}
|
||||
|
||||
postgresURI := os.Getenv("PN_FRIENDS_CONFIG_DATABASE_URI")
|
||||
databaseMaxConnectionsStr := cmp.Or(os.Getenv("PN_FRIENDS_CONFIG_DATABASE_MAX_CONNECTIONS"), "100")
|
||||
aesKey := os.Getenv("PN_FRIENDS_CONFIG_AES_KEY")
|
||||
grpcAPIKey := os.Getenv("PN_FRIENDS_CONFIG_GRPC_API_KEY")
|
||||
grpcServerPort := os.Getenv("PN_FRIENDS_GRPC_SERVER_PORT")
|
||||
authenticationServerPort := os.Getenv("PN_FRIENDS_AUTHENTICATION_SERVER_PORT")
|
||||
secureServerHost := os.Getenv("PN_FRIENDS_SECURE_SERVER_HOST")
|
||||
secureServerPort := os.Getenv("PN_FRIENDS_SECURE_SERVER_PORT")
|
||||
accountGRPCHost := os.Getenv("PN_FRIENDS_ACCOUNT_GRPC_HOST")
|
||||
accountGRPCPort := os.Getenv("PN_FRIENDS_ACCOUNT_GRPC_PORT")
|
||||
accountGRPCAPIKey := os.Getenv("PN_FRIENDS_ACCOUNT_GRPC_API_KEY")
|
||||
|
||||
if strings.TrimSpace(postgresURI) == "" {
|
||||
globals.Logger.Error("PN_FRIENDS_CONFIG_DATABASE_URI environment variable not set")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
databaseMaxConnections, err := strconv.Atoi(databaseMaxConnectionsStr)
|
||||
|
||||
if err != nil {
|
||||
globals.Logger.Errorf("PN_FRIENDS_CONFIG_DATABASE_MAX_CONNECTIONS is not a valid number. Got %s", databaseMaxConnectionsStr)
|
||||
os.Exit(0)
|
||||
} else {
|
||||
globals.DatabaseMaxConnections = databaseMaxConnections
|
||||
}
|
||||
globals.Config = globals.NewConfigParser(globals.Config).SetPrefix("PN_FRIENDS_CONFIG").ParseFromEnv()
|
||||
|
||||
kerberosPassword := make([]byte, 0x10)
|
||||
_, err = rand.Read(kerberosPassword)
|
||||
|
|
@ -70,100 +43,32 @@ func init() {
|
|||
|
||||
globals.KerberosPassword = string(kerberosPassword)
|
||||
|
||||
globals.AuthenticationServerAccount = nex.NewAccount(nex_types.NewPID(1), "Quazal Authentication", globals.KerberosPassword)
|
||||
globals.SecureServerAccount = nex.NewAccount(nex_types.NewPID(2), "Quazal Rendez-Vous", globals.KerberosPassword)
|
||||
globals.GuestAccount = nex.NewAccount(nex_types.NewPID(100), "guest", "MMQea3n!fsik") // * Guest account password is always the same, known to all consoles. Only allow on the friends server
|
||||
|
||||
if strings.TrimSpace(aesKey) == "" {
|
||||
globals.Logger.Error("PN_FRIENDS_CONFIG_AES_KEY environment variable not set")
|
||||
globals.AuthenticationServerAccount = nex.NewAccount(nex_types.NewPID(1), "Quazal Authentication", globals.KerberosPassword, false)
|
||||
globals.SecureServerAccount = nex.NewAccount(nex_types.NewPID(2), "Quazal Rendez-Vous", globals.KerberosPassword, false)
|
||||
globals.GuestAccount = nex.NewAccount(nex_types.NewPID(100), "guest", "MMQea3n!fsik", false)
|
||||
globals.AESKey, err = hex.DecodeString(globals.Config.AESKey)
|
||||
if err != nil {
|
||||
globals.Logger.Criticalf("Failed to decode AES key: %v", err)
|
||||
os.Exit(0)
|
||||
} else {
|
||||
globals.AESKey, err = hex.DecodeString(os.Getenv("PN_FRIENDS_CONFIG_AES_KEY"))
|
||||
if err != nil {
|
||||
globals.Logger.Criticalf("Failed to decode AES key: %v", err)
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
if strings.TrimSpace(grpcAPIKey) == "" {
|
||||
if strings.TrimSpace(globals.Config.GRPCAPIKey) == "" {
|
||||
globals.Logger.Warning("Insecure gRPC server detected. PN_FRIENDS_CONFIG_GRPC_API_KEY environment variable not set")
|
||||
}
|
||||
|
||||
if strings.TrimSpace(grpcServerPort) == "" {
|
||||
globals.Logger.Error("PN_FRIENDS_GRPC_SERVER_PORT environment variable not set")
|
||||
os.Exit(0)
|
||||
if strings.TrimSpace(globals.Config.AccountGRPCAPIKey) == "" {
|
||||
globals.Logger.Warning("Insecure gRPC server detected. PN_FRIENDS_CONFIG_ACCOUNT_GRPC_API_KEY environment variable not set")
|
||||
}
|
||||
|
||||
if port, err := strconv.Atoi(grpcServerPort); err != nil {
|
||||
globals.Logger.Errorf("PN_FRIENDS_GRPC_SERVER_PORT is not a valid port. Expected 0-65535, got %s", grpcServerPort)
|
||||
os.Exit(0)
|
||||
} else if port < 0 || port > 65535 {
|
||||
globals.Logger.Errorf("PN_FRIENDS_GRPC_SERVER_PORT is not a valid port. Expected 0-65535, got %s", grpcServerPort)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if strings.TrimSpace(authenticationServerPort) == "" {
|
||||
globals.Logger.Error("PN_FRIENDS_AUTHENTICATION_SERVER_PORT environment variable not set")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if port, err := strconv.Atoi(authenticationServerPort); err != nil {
|
||||
globals.Logger.Errorf("PN_FRIENDS_AUTHENTICATION_SERVER_PORT is not a valid port. Expected 0-65535, got %s", authenticationServerPort)
|
||||
os.Exit(0)
|
||||
} else if port < 0 || port > 65535 {
|
||||
globals.Logger.Errorf("PN_FRIENDS_AUTHENTICATION_SERVER_PORT is not a valid port. Expected 0-65535, got %s", authenticationServerPort)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if strings.TrimSpace(secureServerHost) == "" {
|
||||
globals.Logger.Error("PN_FRIENDS_SECURE_SERVER_HOST environment variable not set")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if strings.TrimSpace(secureServerPort) == "" {
|
||||
globals.Logger.Error("PN_FRIENDS_SECURE_SERVER_PORT environment variable not set")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if port, err := strconv.Atoi(secureServerPort); err != nil {
|
||||
globals.Logger.Errorf("PN_FRIENDS_SECURE_SERVER_PORT is not a valid port. Expected 0-65535, got %s", secureServerPort)
|
||||
os.Exit(0)
|
||||
} else if port < 0 || port > 65535 {
|
||||
globals.Logger.Errorf("PN_FRIENDS_SECURE_SERVER_PORT is not a valid port. Expected 0-65535, got %s", secureServerPort)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if strings.TrimSpace(accountGRPCHost) == "" {
|
||||
globals.Logger.Error("PN_FRIENDS_ACCOUNT_GRPC_HOST environment variable not set")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if strings.TrimSpace(accountGRPCPort) == "" {
|
||||
globals.Logger.Error("PN_FRIENDS_ACCOUNT_GRPC_PORT environment variable not set")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if port, err := strconv.Atoi(accountGRPCPort); err != nil {
|
||||
globals.Logger.Errorf("PN_FRIENDS_ACCOUNT_GRPC_PORT is not a valid port. Expected 0-65535, got %s", accountGRPCPort)
|
||||
os.Exit(0)
|
||||
} else if port < 0 || port > 65535 {
|
||||
globals.Logger.Errorf("PN_FRIENDS_ACCOUNT_GRPC_PORT is not a valid port. Expected 0-65535, got %s", accountGRPCPort)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if strings.TrimSpace(accountGRPCAPIKey) == "" {
|
||||
globals.Logger.Warning("Insecure gRPC server detected. PN_FRIENDS_ACCOUNT_GRPC_API_KEY environment variable not set")
|
||||
}
|
||||
|
||||
globals.GRPCAccountClientConnection, err = grpc.Dial(fmt.Sprintf("%s:%s", accountGRPCHost, accountGRPCPort), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
globals.GRPCAccountClientConnection, err = grpc.NewClient(fmt.Sprintf("%s:%d", globals.Config.AccountGRPCHost, globals.Config.AccountGRPCPort), grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||
if err != nil {
|
||||
globals.Logger.Criticalf("Failed to connect to account gRPC server: %v", err)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
globals.GRPCAccountClient = pb.NewAccountClient(globals.GRPCAccountClientConnection)
|
||||
globals.GRPCAccountClient = pb.NewAccountServiceClient(globals.GRPCAccountClientConnection)
|
||||
globals.GRPCAccountCommonMetadata = metadata.Pairs(
|
||||
"X-API-Key", accountGRPCAPIKey,
|
||||
"X-API-Key", globals.Config.AccountGRPCAPIKey,
|
||||
)
|
||||
|
||||
database.ConnectPostgres()
|
||||
|
|
|
|||
|
|
@ -3,56 +3,26 @@ package nex_account_management
|
|||
import (
|
||||
"crypto/hmac"
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"strings"
|
||||
|
||||
"github.com/PretendoNetwork/friends/globals"
|
||||
"github.com/PretendoNetwork/friends/utility"
|
||||
nex "github.com/PretendoNetwork/nex-go/v2"
|
||||
"github.com/PretendoNetwork/nex-go/v2/types"
|
||||
account_management "github.com/PretendoNetwork/nex-protocols-go/v2/account-management"
|
||||
account_management_types "github.com/PretendoNetwork/nex-protocols-go/v2/account-management/types"
|
||||
)
|
||||
|
||||
func NintendoCreateAccount(err error, packet nex.PacketInterface, callID uint32, strPrincipalName types.String, strKey types.String, uiGroups types.UInt32, strEmail types.String, oAuthData types.DataHolder) (*nex.RMCMessage, *nex.Error) {
|
||||
if err != nil {
|
||||
globals.Logger.Error(err.Error())
|
||||
return nil, nex.NewError(nex.ResultCodes.Core.InvalidArgument, "") // TODO - Add error message
|
||||
return nil, nex.NewError(nex.ResultCodes.Core.InvalidArgument, err.Error())
|
||||
}
|
||||
|
||||
var tokenBase64 string
|
||||
|
||||
oAuthDataType := oAuthData.Object.DataObjectID().(types.String)
|
||||
|
||||
switch oAuthDataType {
|
||||
case "NintendoCreateAccountData": // * Wii U
|
||||
nintendoCreateAccountData := oAuthData.Object.Copy().(account_management_types.NintendoCreateAccountData)
|
||||
|
||||
tokenBase64 = string(nintendoCreateAccountData.Token)
|
||||
case "AccountExtraInfo": // * 3DS
|
||||
accountExtraInfo := oAuthData.Object.Copy().(account_management_types.AccountExtraInfo)
|
||||
|
||||
tokenBase64 = string(accountExtraInfo.NEXToken)
|
||||
tokenBase64 = strings.Replace(tokenBase64, ".", "+", -1)
|
||||
tokenBase64 = strings.Replace(tokenBase64, "-", "/", -1)
|
||||
tokenBase64 = strings.Replace(tokenBase64, "*", "=", -1)
|
||||
default:
|
||||
globals.Logger.Errorf("Invalid oAuthData data type %s!", oAuthDataType)
|
||||
return nil, nex.NewError(nex.ResultCodes.Authentication.TokenParseError, "") // TODO - Add error message
|
||||
}
|
||||
|
||||
encryptedToken, err := base64.StdEncoding.DecodeString(tokenBase64)
|
||||
if err != nil {
|
||||
globals.Logger.Error(err.Error())
|
||||
return nil, nex.NewError(nex.ResultCodes.Authentication.TokenParseError, "") // TODO - Add error message
|
||||
}
|
||||
|
||||
decryptedToken, err := utility.DecryptToken(encryptedToken)
|
||||
if err != nil {
|
||||
globals.Logger.Error(err.Error())
|
||||
return nil, nex.NewError(nex.ResultCodes.Authentication.TokenParseError, "") // TODO - Add error message
|
||||
decryptedToken, nexError := utility.ValidateNintendoCreateAccountToken(oAuthData)
|
||||
if nexError != nil {
|
||||
globals.Logger.Error(nexError.Error())
|
||||
return nil, nexError
|
||||
}
|
||||
|
||||
pid := types.NewPID(uint64(decryptedToken.UserPID))
|
||||
|
|
@ -64,7 +34,7 @@ func NintendoCreateAccount(err error, packet nex.PacketInterface, callID uint32,
|
|||
_, err = mac.Write(pidByteArray)
|
||||
if err != nil {
|
||||
globals.Logger.Error(err.Error())
|
||||
return nil, nex.NewError(nex.ResultCodes.Authentication.Unknown, "") // TODO - Add error message
|
||||
return nil, nex.NewError(nex.ResultCodes.Authentication.Unknown, err.Error())
|
||||
}
|
||||
|
||||
pidHmac := types.NewString(hex.EncodeToString(mac.Sum(nil)))
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
package nex
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/PretendoNetwork/friends/globals"
|
||||
"github.com/PretendoNetwork/nex-go/v2"
|
||||
)
|
||||
|
|
@ -11,7 +8,10 @@ import (
|
|||
var serverBuildString string
|
||||
|
||||
func StartAuthenticationServer() {
|
||||
port, _ := strconv.Atoi(os.Getenv("PN_FRIENDS_AUTHENTICATION_SERVER_PORT"))
|
||||
|
||||
if globals.Config.HealthCheckPort != 0 {
|
||||
go nex.EnableBasicUDPHealthCheck(int(globals.Config.HealthCheckPort))
|
||||
}
|
||||
|
||||
globals.AuthenticationServer = nex.NewPRUDPServer()
|
||||
globals.AuthenticationEndpoint = nex.NewPRUDPEndPoint(1)
|
||||
|
|
@ -27,5 +27,5 @@ func StartAuthenticationServer() {
|
|||
globals.AuthenticationServer.SessionKeyLength = 16
|
||||
globals.AuthenticationServer.AccessKey = "ridfebb9"
|
||||
globals.AuthenticationServer.BindPRUDPEndPoint(globals.AuthenticationEndpoint)
|
||||
globals.AuthenticationServer.Listen(port)
|
||||
globals.AuthenticationServer.Listen(int(globals.Config.AuthenticationServerPort))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
package nex_friends_wiiu
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/PretendoNetwork/friends/database"
|
||||
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
|
||||
"github.com/PretendoNetwork/friends/globals"
|
||||
|
|
@ -93,7 +91,7 @@ func UpdateAndGetAllInformation(err error, packet nex.PacketInterface, callID ui
|
|||
|
||||
notifications_wiiu.SendPresenceUpdate(presence)
|
||||
|
||||
if os.Getenv("PN_FRIENDS_CONFIG_ENABLE_BELLA") == "true" {
|
||||
if globals.Config.EnableBella {
|
||||
bella := friends_wiiu_types.NewFriendInfo()
|
||||
|
||||
bella.NNAInfo = friends_wiiu_types.NewNNAInfo()
|
||||
|
|
|
|||
|
|
@ -1,9 +1,6 @@
|
|||
package nex
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/PretendoNetwork/friends/globals"
|
||||
"github.com/PretendoNetwork/nex-go/v2/constants"
|
||||
"github.com/PretendoNetwork/nex-go/v2/types"
|
||||
|
|
@ -15,12 +12,10 @@ func registerCommonAuthenticationServerProtocols() {
|
|||
ticketGrantingProtocol := ticket_granting.NewProtocol()
|
||||
commonTicketGrantingProtocol := common_ticket_granting.NewCommonProtocol(ticketGrantingProtocol)
|
||||
|
||||
port, _ := strconv.Atoi(os.Getenv("PN_FRIENDS_SECURE_SERVER_PORT"))
|
||||
|
||||
secureStationURL := types.NewStationURL("")
|
||||
secureStationURL.SetURLType(constants.StationURLPRUDPS)
|
||||
secureStationURL.SetAddress(os.Getenv("PN_FRIENDS_SECURE_SERVER_HOST"))
|
||||
secureStationURL.SetPortNumber(uint16(port))
|
||||
secureStationURL.SetAddress(globals.Config.SecureServerHost)
|
||||
secureStationURL.SetPortNumber(globals.Config.SecureServerPort)
|
||||
secureStationURL.SetConnectionID(1)
|
||||
secureStationURL.SetPrincipalID(types.NewPID(2))
|
||||
secureStationURL.SetStreamID(1)
|
||||
|
|
|
|||
|
|
@ -9,8 +9,12 @@ import (
|
|||
|
||||
func registerCommonSecureServerProtocols() {
|
||||
secureConnectionProtocol := secure_connection.NewProtocol()
|
||||
common_secure_connection.NewCommonProtocol(secureConnectionProtocol)
|
||||
commonSecureConnectionProtocol := common_secure_connection.NewCommonProtocol(secureConnectionProtocol)
|
||||
|
||||
// * On account creation the console logs in with a guest account and uses the Register method
|
||||
commonSecureConnectionProtocol.EnableInsecureRegister()
|
||||
|
||||
// * Override RegisterEx so that we can register the user into the ConnectedUsers map
|
||||
secureConnectionProtocol.RegisterEx = nex_secure_connection.RegisterEx
|
||||
|
||||
globals.SecureEndpoint.RegisterServiceProtocol(secureConnectionProtocol)
|
||||
|
|
|
|||
|
|
@ -3,77 +3,144 @@ package nex_secure_connection
|
|||
import (
|
||||
"net"
|
||||
|
||||
"github.com/PretendoNetwork/nex-go/v2"
|
||||
"github.com/PretendoNetwork/nex-go/v2/constants"
|
||||
"github.com/PretendoNetwork/nex-go/v2/types"
|
||||
secure_connection "github.com/PretendoNetwork/nex-protocols-go/v2/secure-connection"
|
||||
common_globals "github.com/PretendoNetwork/nex-protocols-common-go/v2/globals"
|
||||
|
||||
database_3ds "github.com/PretendoNetwork/friends/database/3ds"
|
||||
database_wiiu "github.com/PretendoNetwork/friends/database/wiiu"
|
||||
"github.com/PretendoNetwork/friends/globals"
|
||||
friends_types "github.com/PretendoNetwork/friends/types"
|
||||
nex "github.com/PretendoNetwork/nex-go/v2"
|
||||
"github.com/PretendoNetwork/nex-go/v2/types"
|
||||
secure_connection "github.com/PretendoNetwork/nex-protocols-go/v2/secure-connection"
|
||||
)
|
||||
|
||||
func RegisterEx(err error, packet nex.PacketInterface, callID uint32, vecMyURLs types.List[types.StationURL], hCustomData types.DataHolder) (*nex.RMCMessage, *nex.Error) {
|
||||
if err != nil {
|
||||
globals.Logger.Error(err.Error())
|
||||
return nil, nex.NewError(nex.ResultCodes.Core.InvalidArgument, "")
|
||||
common_globals.Logger.Error(err.Error())
|
||||
return nil, nex.NewError(nex.ResultCodes.Core.InvalidArgument, err.Error())
|
||||
}
|
||||
|
||||
connection := packet.Sender().(*nex.PRUDPConnection)
|
||||
endpoint := connection.Endpoint()
|
||||
|
||||
retval := types.NewQResultSuccess(nex.ResultCodes.Core.Unknown)
|
||||
|
||||
// TODO - Validate loginData
|
||||
pid := uint32(connection.PID())
|
||||
|
||||
user := friends_types.NewConnectedUser()
|
||||
user.PID = pid
|
||||
user.Connection = connection
|
||||
|
||||
lastOnline := types.NewDateTime(0).Now()
|
||||
loginDataType := hCustomData.Object.DataObjectID().(types.String)
|
||||
|
||||
switch loginDataType {
|
||||
case "NintendoLoginData":
|
||||
user.Platform = friends_types.WUP // * Platform is Wii U
|
||||
|
||||
err = database_wiiu.UpdateUserLastOnlineTime(pid, lastOnline)
|
||||
if err != nil {
|
||||
globals.Logger.Critical(err.Error())
|
||||
retval = types.NewQResultError(nex.ResultCodes.Authentication.Unknown)
|
||||
}
|
||||
case "AccountExtraInfo":
|
||||
user.Platform = friends_types.CTR // * Platform is 3DS
|
||||
|
||||
err = database_3ds.UpdateUserLastOnlineTime(pid, lastOnline)
|
||||
if err != nil {
|
||||
globals.Logger.Critical(err.Error())
|
||||
retval = types.NewQResultError(nex.ResultCodes.Authentication.Unknown)
|
||||
}
|
||||
default:
|
||||
globals.Logger.Errorf("Unknown loginData data type %s!", loginDataType)
|
||||
retval = types.NewQResultError(nex.ResultCodes.Authentication.ValidationFailed)
|
||||
}
|
||||
|
||||
var retval types.QResult
|
||||
pidConnectionID := types.NewUInt32(0)
|
||||
urlPublic := types.NewString("")
|
||||
|
||||
if retval.IsSuccess() {
|
||||
globals.ConnectedUsers.Set(pid, user)
|
||||
errorCode := common_globals.ValidatePretendoLoginData(connection.PID(), hCustomData, globals.AESKey)
|
||||
if errorCode != nil {
|
||||
common_globals.Logger.Error(errorCode.Message)
|
||||
retval = types.NewQResultError(errorCode.ResultCode)
|
||||
} else {
|
||||
// * vecMyURLs may contain multiple StationURLs. Search them all
|
||||
var localStation *types.StationURL
|
||||
var publicStation *types.StationURL
|
||||
|
||||
localStation := vecMyURLs[0]
|
||||
for _, stationURL := range vecMyURLs {
|
||||
natf, ok := stationURL.NATFiltering()
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
address := connection.Address().(*net.UDPAddr)
|
||||
natm, ok := stationURL.NATMapping()
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
localStation.SetAddress(address.IP.String())
|
||||
localStation.SetPortNumber(uint16(address.Port))
|
||||
// * Station reports itself as being non-public (local)
|
||||
if localStation == nil && !stationURL.IsPublic() {
|
||||
localStation = &stationURL
|
||||
}
|
||||
|
||||
localStationURL := localStation.URL()
|
||||
// * Still did not find the station, trying heuristics
|
||||
if localStation == nil && natf == constants.UnknownNATFiltering && natm == constants.UnknownNATMapping {
|
||||
localStation = &stationURL
|
||||
}
|
||||
|
||||
pidConnectionID = types.NewUInt32(connection.ID)
|
||||
urlPublic = types.NewString(localStationURL)
|
||||
if publicStation == nil && stationURL.IsPublic() {
|
||||
publicStation = &stationURL
|
||||
}
|
||||
}
|
||||
|
||||
if localStation == nil {
|
||||
common_globals.Logger.Error("Failed to find local station")
|
||||
return nil, nex.NewError(nex.ResultCodes.Core.InvalidArgument, "change_error")
|
||||
}
|
||||
|
||||
if publicStation == nil {
|
||||
publicStation = localStation
|
||||
|
||||
var address string
|
||||
var port uint16
|
||||
|
||||
// * We have to duplicate this because Go automatically breaks on switch statements
|
||||
switch clientAddress := connection.Address().(type) {
|
||||
case *net.UDPAddr:
|
||||
address = clientAddress.IP.String()
|
||||
port = uint16(clientAddress.Port)
|
||||
case *net.TCPAddr:
|
||||
address = clientAddress.IP.String()
|
||||
port = uint16(clientAddress.Port)
|
||||
}
|
||||
|
||||
publicStation.SetAddress(address)
|
||||
publicStation.SetPortNumber(port)
|
||||
publicStation.SetNATFiltering(constants.UnknownNATFiltering)
|
||||
publicStation.SetNATMapping(constants.UnknownNATMapping)
|
||||
publicStation.SetType(uint8(constants.StationURLFlagPublic) | uint8(constants.StationURLFlagBehindNAT))
|
||||
}
|
||||
|
||||
localStation.SetPrincipalID(connection.PID())
|
||||
publicStation.SetPrincipalID(connection.PID())
|
||||
|
||||
localStation.SetRVConnectionID(connection.ID)
|
||||
publicStation.SetRVConnectionID(connection.ID)
|
||||
|
||||
connection.StationURLs = append(connection.StationURLs, *localStation)
|
||||
connection.StationURLs = append(connection.StationURLs, *publicStation)
|
||||
|
||||
pid := uint32(connection.PID())
|
||||
|
||||
user := friends_types.NewConnectedUser()
|
||||
user.PID = pid
|
||||
user.Connection = connection
|
||||
|
||||
lastOnline := types.NewDateTime(0).Now()
|
||||
loginDataType := hCustomData.Object.DataObjectID().(types.String)
|
||||
|
||||
switch loginDataType {
|
||||
case "NintendoLoginData":
|
||||
user.Platform = friends_types.WUP // * Platform is Wii U
|
||||
|
||||
err = database_wiiu.UpdateUserLastOnlineTime(pid, lastOnline)
|
||||
if err != nil {
|
||||
globals.Logger.Critical(err.Error())
|
||||
retval = types.NewQResultError(nex.ResultCodes.Authentication.Unknown)
|
||||
}
|
||||
case "AccountExtraInfo":
|
||||
user.Platform = friends_types.CTR // * Platform is 3DS
|
||||
|
||||
err = database_3ds.UpdateUserLastOnlineTime(pid, lastOnline)
|
||||
if err != nil {
|
||||
globals.Logger.Critical(err.Error())
|
||||
retval = types.NewQResultError(nex.ResultCodes.Authentication.Unknown)
|
||||
}
|
||||
default:
|
||||
globals.Logger.Errorf("Unknown loginData data type %s!", loginDataType)
|
||||
retval = types.NewQResultError(nex.ResultCodes.Authentication.ValidationFailed)
|
||||
}
|
||||
|
||||
if !retval.IsError() {
|
||||
globals.ConnectedUsers.Set(pid, user)
|
||||
|
||||
retval = types.NewQResultSuccess(nex.ResultCodes.Core.Unknown)
|
||||
pidConnectionID = types.NewUInt32(connection.ID)
|
||||
urlPublic = types.NewString(publicStation.URL())
|
||||
}
|
||||
}
|
||||
|
||||
rmcResponseStream := nex.NewByteStreamOut(globals.SecureEndpoint.LibraryVersions(), globals.SecureEndpoint.ByteStreamSettings())
|
||||
rmcResponseStream := nex.NewByteStreamOut(endpoint.LibraryVersions(), endpoint.ByteStreamSettings())
|
||||
|
||||
retval.WriteTo(rmcResponseStream)
|
||||
pidConnectionID.WriteTo(rmcResponseStream)
|
||||
|
|
@ -81,7 +148,7 @@ func RegisterEx(err error, packet nex.PacketInterface, callID uint32, vecMyURLs
|
|||
|
||||
rmcResponseBody := rmcResponseStream.Bytes()
|
||||
|
||||
rmcResponse := nex.NewRMCSuccess(globals.SecureEndpoint, rmcResponseBody)
|
||||
rmcResponse := nex.NewRMCSuccess(endpoint, rmcResponseBody)
|
||||
rmcResponse.ProtocolID = secure_connection.ProtocolID
|
||||
rmcResponse.MethodID = secure_connection.MethodRegisterEx
|
||||
rmcResponse.CallID = callID
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
package nex
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
database_3ds "github.com/PretendoNetwork/friends/database/3ds"
|
||||
|
|
@ -17,8 +15,6 @@ import (
|
|||
)
|
||||
|
||||
func StartSecureServer() {
|
||||
port, _ := strconv.Atoi(os.Getenv("PN_FRIENDS_SECURE_SERVER_PORT"))
|
||||
|
||||
globals.SecureServer = nex.NewPRUDPServer()
|
||||
globals.SecureEndpoint = nex.NewPRUDPEndPoint(1)
|
||||
|
||||
|
|
@ -66,5 +62,5 @@ func StartSecureServer() {
|
|||
globals.SecureServer.SessionKeyLength = 16
|
||||
globals.SecureServer.AccessKey = "ridfebb9"
|
||||
globals.SecureServer.BindPRUDPEndPoint(globals.SecureEndpoint)
|
||||
globals.SecureServer.Listen(port)
|
||||
globals.SecureServer.Listen(int(globals.Config.SecureServerPort))
|
||||
}
|
||||
|
|
|
|||
70
utility/authentication.go
Normal file
70
utility/authentication.go
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
package utility
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/PretendoNetwork/nex-go/v2"
|
||||
"github.com/PretendoNetwork/nex-go/v2/types"
|
||||
common_globals "github.com/PretendoNetwork/nex-protocols-common-go/v2/globals"
|
||||
account_management_types "github.com/PretendoNetwork/nex-protocols-go/v2/account-management/types"
|
||||
|
||||
"github.com/PretendoNetwork/friends/globals"
|
||||
)
|
||||
|
||||
// ValidateNintendoCreateAccountToken validates the given Pretendo token for account creation
|
||||
func ValidateNintendoCreateAccountToken(token types.DataHolder) (*common_globals.NEXToken, *nex.Error) {
|
||||
var tokenBase64 string
|
||||
|
||||
tokenDataType := token.Object.DataObjectID().(types.String)
|
||||
|
||||
switch tokenDataType {
|
||||
case "NintendoCreateAccountData": // * Wii U
|
||||
nintendoCreateAccountData := token.Object.Copy().(account_management_types.NintendoCreateAccountData)
|
||||
|
||||
tokenBase64 = string(nintendoCreateAccountData.Token)
|
||||
case "AccountExtraInfo": // * 3DS
|
||||
accountExtraInfo := token.Object.Copy().(account_management_types.AccountExtraInfo)
|
||||
|
||||
tokenBase64 = string(accountExtraInfo.NEXToken)
|
||||
tokenBase64 = strings.Replace(tokenBase64, ".", "+", -1)
|
||||
tokenBase64 = strings.Replace(tokenBase64, "-", "/", -1)
|
||||
tokenBase64 = strings.Replace(tokenBase64, "*", "=", -1)
|
||||
default:
|
||||
globals.Logger.Errorf("Invalid token data type %s!", tokenDataType)
|
||||
return nil, nex.NewError(nex.ResultCodes.Authentication.ValidationFailed, fmt.Sprintf("Invalid token data type %s!", tokenDataType))
|
||||
}
|
||||
|
||||
encryptedToken, err := base64.StdEncoding.DecodeString(tokenBase64)
|
||||
if err != nil {
|
||||
globals.Logger.Error(err.Error())
|
||||
return nil, nex.NewError(nex.ResultCodes.Authentication.ValidationFailed, err.Error())
|
||||
}
|
||||
|
||||
decryptedToken, nexError := common_globals.DecryptToken(encryptedToken, globals.AESKey)
|
||||
if nexError != nil {
|
||||
return nil, nexError
|
||||
}
|
||||
|
||||
// Check for NEX token type
|
||||
if decryptedToken.TokenType != 3 {
|
||||
return nil, nex.NewError(nex.ResultCodes.Authentication.ValidationFailed, "Invalid token type")
|
||||
}
|
||||
|
||||
// Expire time is in milliseconds
|
||||
expireTime := time.Unix(int64(decryptedToken.ExpireTime / 1000), 0)
|
||||
|
||||
if expireTime.Before(time.Now()) {
|
||||
return nil, nex.NewError(nex.ResultCodes.Authentication.TokenExpired, "Token expired")
|
||||
}
|
||||
|
||||
// PID isn't checked since account creation is done with a guest account
|
||||
|
||||
if decryptedToken.AccessLevel < 0 {
|
||||
return nil, nex.NewError(nex.ResultCodes.RendezVous.AccountDisabled, fmt.Sprintf("Account %d is banned", decryptedToken.UserPID))
|
||||
}
|
||||
|
||||
return decryptedToken, nil
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
package utility
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash/crc32"
|
||||
|
||||
"github.com/PretendoNetwork/friends/globals"
|
||||
"github.com/PretendoNetwork/friends/types"
|
||||
)
|
||||
|
||||
func DecryptToken(encryptedToken []byte) (*types.NEXToken, error) {
|
||||
// Decrypt the token body
|
||||
block, err := aes.NewCipher(globals.AESKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
expectedChecksum := binary.BigEndian.Uint32(encryptedToken[0:4])
|
||||
encryptedBody := encryptedToken[4:]
|
||||
|
||||
decrypted := make([]byte, len(encryptedBody))
|
||||
iv := make([]byte, 16)
|
||||
mode := cipher.NewCBCDecrypter(block, iv)
|
||||
mode.CryptBlocks(decrypted, encryptedBody)
|
||||
|
||||
paddingSize := int(decrypted[len(decrypted)-1])
|
||||
|
||||
if paddingSize < 0 || paddingSize >= len(decrypted) {
|
||||
return nil, fmt.Errorf("Invalid padding size %d for token %x", paddingSize, encryptedToken)
|
||||
}
|
||||
|
||||
decrypted = decrypted[:len(decrypted)-paddingSize]
|
||||
|
||||
table := crc32.MakeTable(crc32.IEEE)
|
||||
calculatedChecksum := crc32.Checksum(decrypted, table)
|
||||
|
||||
if expectedChecksum != calculatedChecksum {
|
||||
return nil, errors.New("Checksum did not match. Failed decrypt. Are you using the right key?")
|
||||
}
|
||||
|
||||
// Unpack the token body to struct
|
||||
token := &types.NEXToken{}
|
||||
tokenReader := bytes.NewBuffer(decrypted)
|
||||
|
||||
err = binary.Read(tokenReader, binary.LittleEndian, token)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return token, nil
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user