It took me a long time to figure this out, and searched for it myself, but now that I have a working solution, I’d like to share it here:
step 1, create a file named: .aws/credentials
with the following content:
[default]
aws_access_key_id =
aws_secret_access_key =
step 2, add the following line to your docker-compose file:
COPY credentials .aws/credentials
run mkdir /root/.aws
COPY credentials /root/.aws/credentials
step 3, add this to your main.go file:
import (
"context"
"database/sql"
"encoding/json"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/heroiclabs/nakama-common/runtime"
"github.com/heroiclabs/nakama-common/api"
// "github.com/aws/aws-sdk-go/service/s3/s3manager"
)
var svc = s3.New(sess)
const (
AWS_S3_REGION = "<place region here>"
AWS_S3_BUCKET = "<place s3 bucket name here>"
)
// session start
var sess = connectAWS()
func connectAWS() *session.Session {
sess, err := session.NewSession(&aws.Config{Region: aws.String(AWS_S3_REGION)})
if err != nil {
panic(err)
}
return sess
}
// list all files
func listFiles(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) {
svc := s3.New(sess)
input := &s3.ListObjectsInput{
Bucket: aws.String(AWS_S3_BUCKET),
}
result, err := svc.ListObjects(input)
if err != nil {
if aerr, ok := err.(awserr.Error); ok {
switch aerr.Code() {
case s3.ErrCodeNoSuchBucket:
logger.Error(s3.ErrCodeNoSuchBucket, aerr.Error())
default:
logger.Error(aerr.Error())
}
} else {
// Print the error, cast err to awserr.Error to get the Code and
// Message from an error.
logger.Error(err.Error())
}
}
response, err := json.Marshal(result)
if err != nil {
return "", err
}
return string(response), nil
}
// download file
func downloadFile(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) {
var input map[string]string
err := json.Unmarshal([]byte(payload), &input)
if err != nil {
return "", err
}
// Create S3 service client
svc := s3.New(sess)
req, _ := svc.GetObjectRequest(&s3.GetObjectInput{
Bucket: aws.String(AWS_S3_BUCKET),
Key: aws.String(input["url"]),
})
url, err := req.Presign(24 * time.Hour)
if err != nil {
logger.Error("Failed to generate a pre-signed url: ", err)
return "error", err
}
// Display the pre-signed url
// logger.Error(string(json_data) , url)
response := `{ "url" : "` + url + `"}`
return response, nil
}
// upload file
func uploadFile(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) {
var input map[string]string
err := json.Unmarshal([]byte(payload), &input)
if err != nil {
return "", err
}
// userId, ok := ctx.Value(runtime.RUNTIME_CTX_USER_ID).(string)
userId := ctx.Value(runtime.RUNTIME_CTX_USER_ID).(string)
for m := range UserList {
if UserList[m].User_id == userId {
UserList[m] = UserList[len(UserList)-1]
UserList = UserList[:len(UserList)-1]
}
}
var location = input["type"] + "/" + userId + "/" + input["filename"]
svc := s3.New(sess)
req, _ := svc.PutObjectRequest(&s3.PutObjectInput{
Bucket: aws.String(AWS_S3_BUCKET),
Key: aws.String(location),
})
url, err := req.Presign(15 * time.Minute)
if err != nil {
logger.Error("Failed to generate a pre-signed url: ", err)
return "error", err
}
response := `{ "url" : "` + url + `", "location" :"` + location + `"}`
return response, nil
}
func deleteFile(ctx context.Context, logger runtime.Logger, db *sql.DB, nk runtime.NakamaModule, payload string) (string, error) {
var input map[string]string
err := json.Unmarshal([]byte(payload), &input)
if err != nil {
return "", err
}
extensions := []string{".txt", ".json", ".jpeg"}
fileUser := input["user"]
fileType := input["type"]
fileName := input["name"]
userId := ctx.Value(runtime.RUNTIME_CTX_USER_ID).(string)
// recieve current user, userfile, filecollection, filename
// if user is actual user
if userId == fileUser {
// else if user is admin or moderator or artist
// else error
// delete files on aws
svc := s3.New(sess)
for _, i := range extensions {
var location = fileType + "/" + fileUser + "/" + fileName + i
request := &s3.DeleteObjectInput{
Bucket: aws.String(AWS_S3_BUCKET),
Key: aws.String(location),
}
_, err = svc.DeleteObject(request)
if err != nil {
logger.Error("Storage delete error.")
}
}
// delete storage
objectIds := []*runtime.StorageDelete{
&runtime.StorageDelete{
Collection: fileType,
Key: fileName,
UserID: fileUser,
},
}
err = nk.StorageDelete(ctx, objectIds)
if err != nil {
logger.Error("Storage delete error.")
}
}
return "succes", nil
}
Please let me know if things are unclear or have any questions
Linjoe