Skip to content

Commit

Permalink
refactoring: Server API service (#152)
Browse files Browse the repository at this point in the history
* refactor: rename var `mysql*` to `sql*`

The current variable name `mysqlStore` and `mysqlStoreCh` can generate
confusion as it comes from a factory store that support multiple
databases (MySQL and Postgres).

Signed-off-by: Kairo de Araujo <kairo.araujo@testifysec.com>

* refactor: simplify archivista, move API to server

This commit simplifies the archivista cmd (`cmd/archivista`),
removing the API logic to the server, where all handlers for
HTTP requests are implemented.

This also includes the API Swagger documentation.

Signed-off-by: Kairo Araujo <kairo.araujo@testifysec.com>

* refactoring: rename store APIs to upload

This refactoring focuses on the code readability and maintainability
easier for new contributors.

`Store` -> `Upload`
`StoreWithHeaders` -> `UploadWithHeaders`

The `Store` will be exclusive for the Store method used by
`metadataStore` and `objectStore`, causing less confusion.

It renames the functions but keeps backward compatibility to allow
the current users the possibility to migrate.

Signed-off-by: Kairo Araujo <kairo.araujo@testifysec.com>

* tests: Add unit tests for server.go

This add unit tests for main functions for server.go

Signed-off-by: Kairo Araujo <kairo.araujo@testifysec.com>

* fix: Add more consistent HTTP errors

This commit fixes some status codes that can cause misunderstanding.

Some errors were returning Bad Request (400) even when the user
sends a correct request. The errors originating from the
infrastructure or error during operations should raise
Internal Server Error (500) as they are not expected.

Unit tests are included to avoid regression

Signed-off-by: Kairo Araujo <kairo.araujo@testifysec.com>

---------

Signed-off-by: Kairo de Araujo <kairo.araujo@testifysec.com>
Signed-off-by: Kairo Araujo <kairo.araujo@testifysec.com>
  • Loading branch information
kairoaraujo authored Jan 24, 2024
1 parent a059114 commit fe1b2b3
Show file tree
Hide file tree
Showing 13 changed files with 1,101 additions and 55 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/verify-licence.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,4 @@ jobs:
- name: Check license headers
run: |
set -e
addlicense --check -l apache -c 'The Archivista Contributors' --ignore "ent/migrate/migrations/**" -v ./
addlicense --check -l apache -c 'The Archivista Contributors' --ignore "ent/migrate/migrations/**" --ignore "docs/**" -v ./
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ lint: ## Run linter
@go vet ./...


.PHONY: docs
docs: ## Generate swagger docs
@go install github.com/swaggo/swag/cmd/swag@v1.16.2
@swag init -o docs -d internal/server -g server.go -pd

.PHONY: db-migrations
db-migrations: ## Run the migrations for the database
Expand Down
33 changes: 8 additions & 25 deletions cmd/archivista/main.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2022 The Archivista Contributors
// Copyright 2022-2024 The Archivista Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -30,13 +30,8 @@ import (
"syscall"
"time"

"entgo.io/contrib/entgql"
"github.com/99designs/gqlgen/graphql/handler"
"github.com/99designs/gqlgen/graphql/playground"
nested "github.com/antonfisher/nested-logrus-formatter"
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
"github.com/in-toto/archivista"
"github.com/in-toto/archivista/internal/config"
"github.com/in-toto/archivista/internal/metadatastorage/sqlstore"
"github.com/in-toto/archivista/internal/objectstorage/blobstore"
Expand Down Expand Up @@ -97,7 +92,7 @@ func main() {
logrus.Fatalf("could not create ent client: %+v", err)
}

mysqlStore, mysqlStoreCh, err := sqlstore.New(ctx, entClient)
sqlStore, sqlStoreCh, err := sqlstore.New(ctx, entClient)
if err != nil {
logrus.Fatalf("error initializing mysql client: %+v", err)
}
Expand All @@ -108,22 +103,10 @@ func main() {
logrus.Infof("executing phase 3: create and register http service (time since start: %s)", time.Since(startTime))
// ********************************************************************************
now = time.Now()
server := server.New(mysqlStore, fileStore)
router := mux.NewRouter()
router.HandleFunc("/download/{gitoid}", server.GetHandler)
router.HandleFunc("/upload", server.StoreHandler)

if cfg.EnableGraphql {
client := mysqlStore.GetClient()
srv := handler.NewDefaultServer(archivista.NewSchema(client))
srv.Use(entgql.Transactioner{TxOpener: client})
router.Handle("/query", srv)
if cfg.GraphqlWebClientEnable {
router.Handle("/",
playground.Handler("Archivista", "/query"),
)
}
}

// initialize the server
sqlClient := sqlStore.GetClient()
server := server.New(sqlStore, fileStore, cfg, sqlClient)

listenAddress := cfg.ListenOn
listenAddress = strings.ToLower(strings.TrimSpace(listenAddress))
Expand All @@ -146,7 +129,7 @@ func main() {
handlers.AllowedOrigins(cfg.CORSAllowOrigins),
handlers.AllowedMethods([]string{"GET", "POST", "OPTIONS"}),
handlers.AllowedHeaders([]string{"Accept", "Content-Type", "Content-Length", "Accept-Encoding", "X-CSRF-Token", "Authorization"}),
)(router)); err != nil {
)(server.Router())); err != nil {
logrus.Fatalf("unable to start http server: %+v", err)
}
}()
Expand All @@ -156,7 +139,7 @@ func main() {

<-ctx.Done()
<-fileStoreCh
<-mysqlStoreCh
<-sqlStoreCh

logrus.Infof("exiting, uptime: %v", time.Since(startTime))
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/archivistactl/cmd/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func storeAttestationByPath(ctx context.Context, baseUrl, path string) (string,
}

defer file.Close()
resp, err := api.StoreWithReader(ctx, baseUrl, file)
resp, err := api.UploadWithReader(ctx, baseUrl, file)
if err != nil {
return "", err
}
Expand Down
230 changes: 230 additions & 0 deletions docs/docs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
// Package docs Code generated by swaggo/swag. DO NOT EDIT
package docs

import "github.com/swaggo/swag"

const docTemplate = `{
"schemes": {{ marshal .Schemes }},
"swagger": "2.0",
"info": {
"description": "{{escape .Description}}",
"title": "{{.Title}}",
"contact": {
"name": "Archivista Contributors",
"url": "https://github.com/in-toto/archivista/issues/new"
},
"license": {
"url": "https://opensource.org/licenses/Apache-2"
},
"version": "{{.Version}}"
},
"host": "{{.Host}}",
"basePath": "{{.BasePath}}",
"paths": {
"/donwload/{gitoid}": {
"post": {
"description": "download an attestation",
"produces": [
"application/json"
],
"summary": "Download",
"deprecated": true,
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/dsse.Envelope"
}
}
}
}
},
"/upload": {
"post": {
"description": "stores an attestation",
"produces": [
"application/json"
],
"summary": "Store",
"deprecated": true,
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/api.StoreResponse"
}
}
}
}
},
"/v1/donwload/{gitoid}": {
"post": {
"description": "download an attestation",
"produces": [
"application/json"
],
"tags": [
"attestation"
],
"summary": "Download",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/dsse.Envelope"
}
}
}
}
},
"/v1/query": {
"post": {
"description": "GraphQL query",
"produces": [
"application/json"
],
"tags": [
"graphql"
],
"summary": "Query GraphQL",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/archivista.Resolver"
}
}
}
}
},
"/v1/upload": {
"post": {
"description": "stores an attestation",
"produces": [
"application/json"
],
"tags": [
"attestation"
],
"summary": "Store",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/api.StoreResponse"
}
}
}
}
}
},
"definitions": {
"api.StoreResponse": {
"type": "object",
"properties": {
"gitoid": {
"type": "string"
}
}
},
"archivista.Resolver": {
"type": "object"
},
"dsse.Envelope": {
"type": "object",
"properties": {
"payload": {
"type": "array",
"items": {
"type": "integer"
}
},
"payloadType": {
"type": "string"
},
"signatures": {
"type": "array",
"items": {
"$ref": "#/definitions/dsse.Signature"
}
}
}
},
"dsse.Signature": {
"type": "object",
"properties": {
"certificate": {
"type": "array",
"items": {
"type": "integer"
}
},
"intermediates": {
"type": "array",
"items": {
"type": "array",
"items": {
"type": "integer"
}
}
},
"keyid": {
"type": "string"
},
"sig": {
"type": "array",
"items": {
"type": "integer"
}
},
"timestamps": {
"type": "array",
"items": {
"$ref": "#/definitions/dsse.SignatureTimestamp"
}
}
}
},
"dsse.SignatureTimestamp": {
"type": "object",
"properties": {
"data": {
"type": "array",
"items": {
"type": "integer"
}
},
"type": {
"$ref": "#/definitions/dsse.SignatureTimestampType"
}
}
},
"dsse.SignatureTimestampType": {
"type": "string",
"enum": [
"tsp"
],
"x-enum-varnames": [
"TimestampRFC3161"
]
}
}
}`

// SwaggerInfo holds exported Swagger Info so clients can modify it
var SwaggerInfo = &swag.Spec{
Version: "v1",
Host: "",
BasePath: "",
Schemes: []string{},
Title: "Archivista API",
Description: "Archivista API",
InfoInstanceName: "swagger",
SwaggerTemplate: docTemplate,
LeftDelim: "{{",
RightDelim: "}}",
}

func init() {
swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
}
Loading

0 comments on commit fe1b2b3

Please sign in to comment.