Skip to content
Snippets Groups Projects
Commit 51932068 authored by Cornel Rautenbach's avatar Cornel Rautenbach
Browse files

Merge branch 'main' of gitlab.com:uafrica/go-utils

parents 13b313b9 3e4135af
Branches
Tags
No related merge requests found
LICENSE 0 → 100644
BSD 3-Clause License
Copyright (c) 2022, uAfrica Technologies (Pty) Ltd
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
...@@ -2,19 +2,24 @@ ...@@ -2,19 +2,24 @@
A set of utilities used by our Golang projects A set of utilities used by our Golang projects
* [errors](./errors/README.md) * [errors](./errors/README.md)
## Creating a new tag ## Creating a new release
When making changes, a new tag needs to be made in order to use the updated library in your project. First pull the tags, and check the latest version. When making changes, a new release needs to be made in order to use the updated library in your project.
`git pull --tags` 1. First, make sure your `uafrica-tools` repository is up to date (minimum at commit `442f62f0`):
```
`git tag` git pull
make install
The output will be a list of tags. Create a new tag with the version number increased. E.g. if the last tag was `v1.2.7`, the new tag could be `v1.2.8`. Then push the tag. ```
`git tag -a v1.2.8 -m "Tag v1.2.8"` 2. After your changes have been merged to the `main` branch of `go-utils`, run the following command which will automatically create a new tag:
```
`git push --tags` ua release
```
For your project, upgrade to the new version by running the `go get` command. and select project `uafrica/go-utils`
`go get gitlab.com/uafrica/go-utils@v1.2.8` 3. For your project, upgrade to the new version by running the `go get` command and specifying the new tab:
\ No newline at end of file ```
go get gitlab.com/uafrica/go-utils@v1.6.0
```
**Note:** The release documentation can be found in GitLab, by navigating to the new tag. For example: https://gitlab.com/uafrica/go-utils/-/tags/v1.6.0
...@@ -27,6 +27,12 @@ type S3UploadResponse struct { ...@@ -27,6 +27,12 @@ type S3UploadResponse struct {
FileSize int `json:"file_size"` FileSize int `json:"file_size"`
} }
type S3UploadSettings struct {
MimeType MIMEType
RetrieveSignedUrl bool
ExpiryDuration *time.Duration
}
type MIMEType string type MIMEType string
const ( const (
...@@ -48,6 +54,9 @@ const ( ...@@ -48,6 +54,9 @@ const (
// MIMETypeImage defines the constant for the Image MIME type. // MIMETypeImage defines the constant for the Image MIME type.
MIMETypeImage MIMEType = "image/*" MIMETypeImage MIMEType = "image/*"
// MIMETypePNG defines the constant for the PNG MIME type.
MIMETypePNG MIMEType = "image/png"
// MIMETypeDefault defines the constant for the default MIME type. // MIMETypeDefault defines the constant for the default MIME type.
MIMETypeDefault MIMEType = "application/octet-stream" MIMETypeDefault MIMEType = "application/octet-stream"
...@@ -68,7 +77,7 @@ func NewSession(session *session.Session) *SessionWithHelpers { ...@@ -68,7 +77,7 @@ func NewSession(session *session.Session) *SessionWithHelpers {
} }
} }
func (s SessionWithHelpers) Upload(data []byte, bucket, fileName string, metadata *map[string]*string, isDebug bool) (*s3.PutObjectOutput, error) { func (s SessionWithHelpers) Upload(data []byte, bucket, fileName string, metadata *map[string]*string) (*s3.PutObjectOutput, error) {
mimeType := getTypeForFilename(fileName) mimeType := getTypeForFilename(fileName)
putInput := &s3.PutObjectInput{ putInput := &s3.PutObjectInput{
Bucket: aws.String(bucket), Bucket: aws.String(bucket),
...@@ -89,18 +98,21 @@ func (s SessionWithHelpers) Upload(data []byte, bucket, fileName string, metadat ...@@ -89,18 +98,21 @@ func (s SessionWithHelpers) Upload(data []byte, bucket, fileName string, metadat
return response, nil return response, nil
} }
func (s SessionWithHelpers) UploadWith1DayExpiry(data []byte, bucket, fileName string, mimeType MIMEType, isDebug bool) (string, error) { func (s SessionWithHelpers) UploadWithSettings(data []byte, bucket, fileName string, settings S3UploadSettings) (string, error) {
if mimeType == "" { if settings.MimeType == "" {
mimeType = getTypeForFilename(fileName) settings.MimeType = getTypeForFilename(fileName)
} }
expiry := time.Now().Add(24 * time.Hour)
putInput := &s3.PutObjectInput{ putInput := &s3.PutObjectInput{
Bucket: aws.String(bucket), Bucket: aws.String(bucket),
Key: aws.String(fileName), Key: aws.String(fileName),
ContentType: aws.String(string(mimeType)), ContentType: aws.String(string(settings.MimeType)),
Body: bytes.NewReader(data), Body: bytes.NewReader(data),
Expires: &expiry, }
if settings.ExpiryDuration != nil {
expiry := time.Now().Add(*settings.ExpiryDuration)
putInput.Expires = &expiry
} }
_, err := s.S3Session.PutObject(putInput) _, err := s.S3Session.PutObject(putInput)
...@@ -108,33 +120,33 @@ func (s SessionWithHelpers) UploadWith1DayExpiry(data []byte, bucket, fileName s ...@@ -108,33 +120,33 @@ func (s SessionWithHelpers) UploadWith1DayExpiry(data []byte, bucket, fileName s
return "", err return "", err
} }
return s.GetSignedDownloadURL(bucket, fileName, 24*time.Hour, isDebug) if settings.RetrieveSignedUrl {
return s.GetSignedDownloadURL(bucket, fileName, 24*time.Hour)
} }
func (s SessionWithHelpers) UploadWithExpiry(data []byte, bucket, fileName string, expiryDuration time.Duration, mimeType MIMEType, isDebug bool) (string, error) { return "", nil
if mimeType == "" {
mimeType = getTypeForFilename(fileName)
} }
expiry := time.Now().Add(expiryDuration) func (s SessionWithHelpers) UploadWith1DayExpiry(data []byte, bucket, fileName string, mimeType MIMEType) (string, error) {
putInput := &s3.PutObjectInput{ if mimeType == "" {
Bucket: aws.String(bucket), mimeType = getTypeForFilename(fileName)
Key: aws.String(fileName),
ContentType: aws.String(string(mimeType)),
Body: bytes.NewReader(data),
Expires: &expiry,
} }
_, err := s.S3Session.PutObject(putInput) expiry := 24 * time.Hour
signedUrl, err := s.UploadWithSettings(data, bucket, fileName, S3UploadSettings{
MimeType: mimeType,
RetrieveSignedUrl: true,
ExpiryDuration: &expiry,
})
if err != nil { if err != nil {
return "", err return "", err
} }
return s.GetSignedDownloadURL(bucket, fileName, 24*time.Hour, isDebug) return signedUrl, nil
} }
// GetSignedDownloadURL gets a signed download URL for the duration. If scv is nil, a new session will be created. // GetSignedDownloadURL gets a signed download URL for the duration. If scv is nil, a new session will be created.
func (s SessionWithHelpers) GetSignedDownloadURL(bucket string, fileName string, duration time.Duration, isDebug bool) (string, error) { func (s SessionWithHelpers) GetSignedDownloadURL(bucket string, fileName string, duration time.Duration) (string, error) {
getInput := &s3.GetObjectInput{ getInput := &s3.GetObjectInput{
Bucket: aws.String(bucket), Bucket: aws.String(bucket),
Key: aws.String(fileName), Key: aws.String(fileName),
...@@ -173,10 +185,15 @@ func (s SessionWithHelpers) FileExists(bucket string, fileName string) (bool, er ...@@ -173,10 +185,15 @@ func (s SessionWithHelpers) FileExists(bucket string, fileName string) (bool, er
} }
// UploadWithFileExtension will upload a file to S3 and return a standard S3UploadResponse. // UploadWithFileExtension will upload a file to S3 and return a standard S3UploadResponse.
func (s SessionWithHelpers) UploadWithFileExtension(data []byte, bucket, filePrefix string, fileExt string, mimeType MIMEType, isDebug bool) (*S3UploadResponse, error) { func (s SessionWithHelpers) UploadWithFileExtension(data []byte, bucket, filePrefix, fileExt string, mimeType MIMEType) (*S3UploadResponse, error) {
fileName := fmt.Sprintf("%s_%s.%s", filePrefix, uuid.New().String(), fileExt) fileName := fmt.Sprintf("%s_%s.%s", filePrefix, uuid.New().String(), fileExt)
uploadUrl, err := s.UploadWith1DayExpiry(data, bucket, fileName, mimeType, isDebug) duration := 24 * time.Hour
uploadUrl, err := s.UploadWithSettings(data, bucket, fileName, S3UploadSettings{
MimeType: mimeType,
RetrieveSignedUrl: true,
ExpiryDuration: &duration,
})
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -298,12 +315,19 @@ func (s SessionWithHelpers) DeleteObjectFromBucket(bucket string, fileName strin ...@@ -298,12 +315,19 @@ func (s SessionWithHelpers) DeleteObjectFromBucket(bucket string, fileName strin
} }
func GetS3FileKey(fileName string, folder string) string { func GetS3FileKey(fileName string, folder string) string {
var fileKey string
// Trim leading and trailing slashes // Trim leading and trailing slashes
fileName = strings.TrimLeft(fileName, "/") fileName = strings.TrimLeft(fileName, "/")
fileName = strings.TrimRight(fileName, "/") fileName = strings.TrimRight(fileName, "/")
if folder != "" {
folder = strings.TrimLeft(folder, "/") folder = strings.TrimLeft(folder, "/")
folder = strings.TrimRight(folder, "/") folder = strings.TrimRight(folder, "/")
fileKey += "/" + folder
}
fileKey += "/" + fileName
return "/" + folder + "/" + fileName return fileKey
} }
package string_utils
import "regexp"
const snakeCasePattern = `[a-z]([a-z0-9_]*[a-z0-9])*`
var snakeCaseRegex = regexp.MustCompile("^" + snakeCasePattern + "$")
func IsSnakeCase(name string) bool {
return snakeCaseRegex.MatchString(name)
}
...@@ -14,6 +14,23 @@ import ( ...@@ -14,6 +14,23 @@ import (
"golang.org/x/text/unicode/norm" "golang.org/x/text/unicode/norm"
) )
const snakeCasePattern = `[a-z]([a-z0-9_]*[a-z0-9])*`
var snakeCaseRegex = regexp.MustCompile("^" + snakeCasePattern + "$")
func IsSnakeCase(name string) bool {
return snakeCaseRegex.MatchString(name)
}
func SnakeToKebabString(s string) string {
s = strings.TrimSpace(s)
re := regexp.MustCompile("(_)")
s = re.ReplaceAllString(s, "-")
return s
}
// ReplaceNonSpacingMarks removes diacritics e.g. êžů becomes ezu // ReplaceNonSpacingMarks removes diacritics e.g. êžů becomes ezu
func ReplaceNonSpacingMarks(str string) string { func ReplaceNonSpacingMarks(str string) string {
t := transform.Chain(norm.NFD, runes.Remove(runes.In(unicode.Mn)), norm.NFC) // Mn: non-spacing marks t := transform.Chain(norm.NFD, runes.Remove(runes.In(unicode.Mn)), norm.NFC) // Mn: non-spacing marks
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment