Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge develop into main #108

Merged
merged 1 commit into from
Jul 2, 2024
Merged
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
- Expose TPS API for adding images [#106](https://github.com/rokwire/content-building-block/issues/106)

## [1.7.0] - 2024-06-26
### Added
Expand Down
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ COPY --from=builder /content-app/driver/web/docs/gen/def.yaml /driver/web/docs/g
COPY --from=builder /content-app/driver/web/authorization_model.conf /driver/web/authorization_model.conf
COPY --from=builder /content-app/driver/web/authorization_policy.csv /driver/web/authorization_policy.csv
COPY --from=builder /content-app/driver/web/authorization_bbs_permission_policy.csv /driver/web/authorization_bbs_permission_policy.csv
COPY --from=builder /content-app/driver/web/authorization_tps_permission_policy.csv /driver/web/authorization_tps_permission_policy.csv

COPY --from=builder /content-app/vendor/github.com/rokwire/core-auth-library-go/v2/authorization/authorization_model_scope.conf /content-app/vendor/github.com/rokwire/core-auth-library-go/v2/authorization/authorization_model_scope.conf
COPY --from=builder /content-app/vendor/github.com/rokwire/core-auth-library-go/v2/authorization/authorization_model_string.conf /content-app/vendor/github.com/rokwire/core-auth-library-go/v2/authorization/authorization_model_string.conf
Expand Down
14 changes: 11 additions & 3 deletions driver/web/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type Adapter struct {
apisHandler rest.ApisHandler
adminApisHandler rest.AdminApisHandler
bbsApisHandler rest.BBsApisHandler
tpsApisHandler rest.TPsApisHandler

app *core.Application

Expand Down Expand Up @@ -192,7 +193,11 @@ func (we Adapter) Start() {

// handle bbs apis
bbsSubRouter := contentRouter.PathPrefix("/bbs").Subrouter()
bbsSubRouter.HandleFunc("/image", we.bbsAuthWrapFunc(we.bbsApisHandler.UploadImage, we.auth.bbs.Permissions)).Methods("POST")
bbsSubRouter.HandleFunc("/image", we.authWrapFunc(we.bbsApisHandler.UploadImage, we.auth.bbs.Permissions)).Methods("POST")

// handle tps apis
tpsSubRouter := contentRouter.PathPrefix("/tps").Subrouter()
tpsSubRouter.HandleFunc("/image", we.authWrapFunc(we.tpsApisHandler.UploadImage, we.auth.tps.Permissions)).Methods("POST")

log.Fatal(http.ListenAndServe(":"+we.port, router))
}
Expand Down Expand Up @@ -268,7 +273,7 @@ func (we Adapter) coreAuthWrapFunc(handler coreAuthFunc, authorization Authoriza

type bbsAuthFunc = func(*tokenauth.Claims, http.ResponseWriter, *http.Request)

func (we Adapter) bbsAuthWrapFunc(handler bbsAuthFunc, authorization tokenauth.Handler) http.HandlerFunc {
func (we Adapter) authWrapFunc(handler bbsAuthFunc, authorization tokenauth.Handler) http.HandlerFunc {
return func(w http.ResponseWriter, req *http.Request) {
utils.LogRequest(req)

Expand All @@ -294,8 +299,11 @@ func NewWebAdapter(host string, port string, app *core.Application, serviceRegMa
apisHandler := rest.NewApisHandler(app)
adminApisHandler := rest.NewAdminApisHandler(app)
bbsApisHandler := rest.NewBBSApisHandler(app)
tpsApisHandler := rest.NewTPSApisHandler(app)
return Adapter{host: host, port: port, cachedYamlDoc: yamlDoc, auth: auth,
apisHandler: apisHandler, adminApisHandler: adminApisHandler, bbsApisHandler: bbsApisHandler, app: app, logger: logger}
apisHandler: apisHandler, adminApisHandler: adminApisHandler,
bbsApisHandler: bbsApisHandler, tpsApisHandler: tpsApisHandler,
app: app, logger: logger}
}

// AppListener implements core.ApplicationListener interface
Expand Down
33 changes: 32 additions & 1 deletion driver/web/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type Authorization interface {
type Auth struct {
coreAuth *CoreAuth
bbs tokenauth.Handlers
tps tokenauth.Handlers
logger *logs.Logger
}

Expand All @@ -50,7 +51,13 @@ func NewAuth(app *core.Application, serviceRegManager *authservice.ServiceRegMan
}
bbsHandlers := tokenauth.NewHandlers(bbsStandardHandler) //add permissions, user and authenticated

auth := Auth{coreAuth: coreAuth, bbs: bbsHandlers, logger: logger}
tpsStandardHandler, err := newTPsStandardHandler(serviceRegManager)
if err != nil {
return nil
}
tpsHandlers := tokenauth.NewHandlers(tpsStandardHandler) //add permissions, user and authenticated

auth := Auth{coreAuth: coreAuth, bbs: bbsHandlers, tps: tpsHandlers, logger: logger}
return &auth
}

Expand Down Expand Up @@ -105,6 +112,30 @@ func newBBsStandardHandler(serviceRegManager *authservice.ServiceRegManager) (*t
return &auth, nil
}

// TPs auth ///////////
func newTPsStandardHandler(serviceRegManager *authservice.ServiceRegManager) (*tokenauth.StandardHandler, error) {
tpsPermissionAuth := authorization.NewCasbinStringAuthorization("driver/web/authorization_tps_permission_policy.csv")
tpsTokenAuth, err := tokenauth.NewTokenAuth(true, serviceRegManager, tpsPermissionAuth, nil)
if err != nil {
return nil, errors.WrapErrorAction(logutils.ActionCreate, "tps token auth", nil, err)
}

check := func(claims *tokenauth.Claims, req *http.Request) (int, error) {
if !claims.Service {
return http.StatusUnauthorized, errors.ErrorData(logutils.StatusInvalid, "service claim", nil)
}

if claims.FirstParty {
return http.StatusUnauthorized, errors.ErrorData(logutils.StatusInvalid, "first party claim", nil)
}

return http.StatusOK, nil
}

auth := tokenauth.NewStandardHandler(*tpsTokenAuth, check)
return &auth, nil
}

// PermissionsAuth entity
// This enforces that the user has permissions matching the policy
type PermissionsAuth struct {
Expand Down
1 change: 1 addition & 0 deletions driver/web/authorization_tps_permission_policy.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
p, tps_upload-images, /content/tps/image, (POST), Allow uploading images
51 changes: 51 additions & 0 deletions driver/web/docs/gen/def.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2869,6 +2869,57 @@ paths:
description: Unauthorized
'500':
description: Internal error
/tps/image:
post:
tags:
- TPs
summary: Uploads an image to the Rokwire system
description: |
Uploads an image to the Rokwire system
security:
- bearerAuth: []
parameters:
- name: height
in: query
description: height of the image to resize.
required: true
style: form
explode: false
schema:
type: string
- name: width
in: query
description: width of the image to resize
required: true
style: form
explode: false
schema:
type: string
- name: quality
in: query
description: quality of the image. Default - 100
required: true
style: form
explode: false
schema:
type: string
- name: fileName
in: query
description: the uploaded file name
required: true
style: form
explode: false
schema:
type: string
responses:
'200':
description: Success
'400':
description: Bad request
'401':
description: Unauthorized
'500':
description: Internal error
components:
securitySchemes:
bearerAuth:
Expand Down
4 changes: 4 additions & 0 deletions driver/web/docs/index.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ paths:
#BBs
/bbs/image:
$ref: "./resources/bbs/image.yaml"

#TPs
/tps/image:
$ref: "./resources/tps/image.yaml"

components:
securitySchemes:
Expand Down
50 changes: 50 additions & 0 deletions driver/web/docs/resources/tps/image.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
post:
tags:
- TPs
summary: Uploads an image to the Rokwire system
description: |
Uploads an image to the Rokwire system
security:
- bearerAuth: []
parameters:
- name: height
in: query
description: height of the image to resize.
required: true
style: form
explode: false
schema:
type: string
- name: width
in: query
description: width of the image to resize
required: true
style: form
explode: false
schema:
type: string
- name: quality
in: query
description: quality of the image. Default - 100
required: true
style: form
explode: false
schema:
type: string
- name: fileName
in: query
description: the uploaded file name
required: true
style: form
explode: false
schema:
type: string
responses:
200:
description: Success
400:
description: Bad request
401:
description: Unauthorized
500:
description: Internal error
5 changes: 5 additions & 0 deletions driver/web/rest/apis.go
Original file line number Diff line number Diff line change
Expand Up @@ -868,3 +868,8 @@ func NewAdminApisHandler(app *core.Application) AdminApisHandler {
func NewBBSApisHandler(app *core.Application) BBsApisHandler {
return BBsApisHandler{app: app}
}

// NewTPSApisHandler creates new rest Handler instance
func NewTPSApisHandler(app *core.Application) TPsApisHandler {
return TPsApisHandler{app: app}
}
97 changes: 97 additions & 0 deletions driver/web/rest/tpsapis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright 2022 Board of Trustees of the University of Illinois.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package rest

import (
"content/core"
"content/core/model"
"encoding/json"
"io/ioutil"
"log"
"net/http"

"github.com/rokwire/core-auth-library-go/v2/tokenauth"
)

// TPsApisHandler handles the rest TPs APIs implementation
type TPsApisHandler struct {
app *core.Application
}

// UploadImage Uploads an image to the Rokwire system
func (h TPsApisHandler) UploadImage(claims *tokenauth.Claims, w http.ResponseWriter, r *http.Request) {
path := "tps-images"

heightParam := intPostValueFromString(r.PostFormValue("height"))
widthParam := intPostValueFromString(r.PostFormValue("width"))
qualityParam := intPostValueFromString(r.PostFormValue("quality"))
imgSpec := model.ImageSpec{Height: heightParam, Width: widthParam, Quality: qualityParam}

// validate file size
r.Body = http.MaxBytesReader(w, r.Body, maxUploadSize)
if err := r.ParseMultipartForm(maxUploadSize); err != nil {
log.Print("File is too big\n")
http.Error(w, "File is too big", http.StatusBadRequest)
return
}

// parse and validate file and post parameters
file, _, err := r.FormFile("fileName")
if err != nil {
log.Print("Invalid file\n")
http.Error(w, "Invalid file", http.StatusBadRequest)
return
}
defer file.Close()
fileBytes, err := ioutil.ReadAll(file)
if err != nil {
log.Print("Invalid file\n")
http.Error(w, "Invalid file", http.StatusBadRequest)
return
}

// check file type, detectcontenttype only needs the first 512 bytes
filetype := http.DetectContentType(fileBytes)
switch filetype {
case "image/jpeg", "image/jpg":
case "image/gif", "image/png":
case "image/webp":
break
default:
log.Print("Invalid file type\n")
http.Error(w, "Invalid file type", http.StatusBadRequest)
return
}

// pass the file to be processed by the use case handler
url, err := h.app.Services.UploadImage(fileBytes, path, imgSpec)
if err != nil {
log.Printf("Error converting image: %s\n", err)
http.Error(w, "Error converting image", http.StatusInternalServerError)
return
}

jsonData := map[string]string{"url": *url}
jsonBynaryData, err := json.Marshal(jsonData)
if err != nil {
log.Println("Error on marshal s3 location data")
http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError)
return
}

w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(http.StatusOK)
w.Write(jsonBynaryData)
}
Loading