Skip to content

Commit

Permalink
wip: create signing key
Browse files Browse the repository at this point in the history
  • Loading branch information
katallaxie authored Apr 24, 2024
1 parent 197bcc6 commit 9283acf
Show file tree
Hide file tree
Showing 15 changed files with 2,186 additions and 237 deletions.
173 changes: 171 additions & 2 deletions api/api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,149 @@ paths:
parameters:
operatorId: "$response.body#/id"

/operators/{operatorId}:
get:
summary: Gets an operator by ID
operationId: getOperator
parameters:
- $ref: "#/components/parameters/operatorId"
responses:
"200":
description: Successful
content:
application/json:
schema:
$ref: "#/components/schemas/Operator"
put:
summary: Updates an operator by ID
operationId: updateOperator
parameters:
- $ref: "#/components/parameters/operatorId"
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/Operator"
responses:
"200":
description: Successful
content:
application/json:
schema:
$ref: "#/components/schemas/Operator"
delete:
summary: Deletes an operator by ID
operationId: deleteOperator
parameters:
- $ref: "#/components/parameters/operatorId"
responses:
"204":
description: Successful

/operators/{operatorId}/signing-keys:
get:
summary: List all signing keys for an operator
operationId: listOperatorSigningKeys
tags:
- Operator
produces:
- "application/json"
parameters:
- $ref: "#/components/parameters/operatorId"
- $ref: "#/components/parameters/offsetParam"
- $ref: "#/components/parameters/limitParam"
security:
- bearerAuth: ["read:signing-keys"]
responses:
"200":
description: Successfull response
content:
application/json:
schema:
allOf:
- $ref: "#/components/schemas/PaginatedResult"
- type: object
properties:
results:
type: array
items:
$ref: "#/components/schemas/KeyPair"
post:
summary: Creates a new signing key
operationId: createOperatorSigningKey
tags:
- Operator
produces:
- "application/json"
parameters:
- $ref: "#/components/parameters/operatorId"
responses:
"201":
description: Created
content:
application/json:
schema:
$ref: "#/components/schemas/KeyPair"
links:
GetSigningKeyById:
operationId: getSigningKey
parameters:
operatorId: "$response.body#/operatorId"
signingKeyId: "$response.body#/id"

/operators/{operatorId}/accounts:
get:
summary: List all accounts for an operator
operationId: listOperatorAccounts
tags:
- Operator
produces:
- "application/json"
parameters:
- $ref: "#/components/parameters/operatorId"
- $ref: "#/components/parameters/offsetParam"
- $ref: "#/components/parameters/limitParam"
security:
- bearerAuth: ["read:accounts"]
responses:
"200":
description: Successfull response
content:
application/json:
schema:
allOf:
- $ref: "#/components/schemas/PaginatedResult"
- type: object
properties:
results:
type: array
items:
$ref: "#/components/schemas/Account"
post:
summary: Creates a new account
operationId: createOperatorAccount
tags:
- Operator
produces:
- "application/json"
parameters:
- $ref: "#/components/parameters/operatorId"
requestBody:
$ref: "#/components/requestBodies/CreateAccount"
responses:
"201":
description: Created
content:
application/json:
schema:
$ref: "#/components/schemas/Account"
links:
GetAccountById:
operationId: getAccount
parameters:
operatorId: "$response.body#/operatorId"
accountId: "$response.body#/id"

/teams:
get:
summary: List all teams
Expand Down Expand Up @@ -164,7 +307,7 @@ paths:
/teams/{teamId}/accounts:
get:
summary: List all accounts for a team
operationId: listAccounts
operationId: listTeamAccounts
tags:
- Team
produces:
Expand Down Expand Up @@ -595,6 +738,14 @@ components:
maximum: 50
default: 20
description: The numbers of items to return.
operatorId:
in: path
name: operatorId
required: true
schema:
type: string
format: uuid
description: The id of the operator to retrieve.

requestBodies:
CreateTeam:
Expand All @@ -616,6 +767,18 @@ components:
type: string
contactEmail:
type: string
CreateAccount:
content:
application/json:
schema:
type: object
required:
- name
properties:
name:
type: string
description:
type: string

securitySchemes:
cookieAuth:
Expand Down Expand Up @@ -709,7 +872,7 @@ components:
properties:
id:
type: string
format: base32
format: uuid
readOnly: true
name:
type: string
Expand Down Expand Up @@ -797,6 +960,12 @@ components:
type: string
contactEmail:
type: string
key:
$ref: "#/components/schemas/KeyPair"
signingKeys:
type: array
items:
$ref: "#/components/schemas/KeyPair"
createdAt:
type: string
format: date-time
Expand Down
32 changes: 31 additions & 1 deletion internal/api/adapters/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package adapters
import (
"context"

"github.com/google/uuid"
"github.com/zeiss/typhoon/internal/api/models"
"github.com/zeiss/typhoon/internal/api/ports"

Expand Down Expand Up @@ -30,12 +31,14 @@ func (db *DB) RunMigrations() error {
return db.conn.AutoMigrate(
&models.NKey{},
&models.Operator{},
&models.Account{},
&models.System{},
&models.Token{},
)
}

// GetOperator ...
func (db *DB) GetOperator(ctx context.Context, id string) (*models.Operator, error) {
func (db *DB) GetOperator(ctx context.Context, id uuid.UUID) (*models.Operator, error) {
operator := &models.Operator{}
if err := db.conn.Where("id = ?", id).First(operator).Error; err != nil {
return nil, err
Expand All @@ -44,6 +47,33 @@ func (db *DB) GetOperator(ctx context.Context, id string) (*models.Operator, err
return operator, nil
}

// DeleteOperator ...
func (db *DB) DeleteOperator(ctx context.Context, id uuid.UUID) error {
return db.conn.WithContext(ctx).Where("id = ?", id).Delete(&models.Operator{}).Error
}

// CreateAccount ...
func (db *DB) CreateAccount(ctx context.Context, account *models.Account) error {
return db.conn.WithContext(ctx).Create(account).Error
}

// CreateOperatorSigningKey ...
func (db *DB) CreateOperatorSigningKey(ctx context.Context, operatorID uuid.UUID, key *models.NKey) error {
return db.conn.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
var operator models.Operator
if err := tx.Where("id = ?", operatorID).First(&operator).Error; err != nil {
return err
}

err := tx.Model(&operator).Association("SigningKeys").Append(key)
if err != nil {
return err
}

return nil
})
}

// ListOperator ...
func (db *DB) ListOperator(ctx context.Context, pagination models.Pagination[*models.Operator]) (*models.Pagination[*models.Operator], error) {
operators := []*models.Operator{}
Expand Down
61 changes: 55 additions & 6 deletions internal/api/controllers/operators.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,40 @@ package controllers
import (
"context"

"github.com/google/uuid"
"github.com/nats-io/nkeys"
"github.com/zeiss/typhoon/internal/api/models"
"github.com/zeiss/typhoon/internal/api/ports"
)

// OperatorsController ...
type OperatorsController struct {
db ports.Operators
db ports.Repositories
}

// NewOperatorsController ...
func NewOperatorsController(db ports.Operators) *OperatorsController {
func NewOperatorsController(db ports.Repositories) *OperatorsController {
return &OperatorsController{db}
}

// CreateOperator ...
func (c *OperatorsController) CreateOperator(ctx context.Context, name string) (*models.Operator, error) {
key, err := nkeys.CreateOperator()
pk, err := nkeys.CreateOperator()
if err != nil {
return nil, err
}

id, err := key.PublicKey()
id, err := pk.PublicKey()
if err != nil {
return nil, err
}

seed, err := key.Seed()
seed, err := pk.Seed()
if err != nil {
return nil, err
}

op := &models.Operator{
ID: id,
Key: models.NKey{
ID: id,
Seed: seed,
Expand All @@ -51,6 +51,55 @@ func (c *OperatorsController) CreateOperator(ctx context.Context, name string) (
return op, nil
}

// CreateOperatorAccount ...
func (c *OperatorsController) CreateOperatorAccount(ctx context.Context, name string, operatorID uuid.UUID) (*models.Account, error) {
key, err := nkeys.CreateAccount()
if err != nil {
return nil, err
}

id, err := key.PublicKey()
if err != nil {
return nil, err
}

seed, err := key.Seed()
if err != nil {
return nil, err
}

account := &models.Account{
Name: name,
OperatorID: operatorID,
Key: models.NKey{
ID: id,
Seed: seed,
},
}

err = c.db.CreateAccount(ctx, account)
if err != nil {
return nil, err
}

return account, nil
}

// CreateOperatorSigningKey ...
func (c *OperatorsController) CreateOperatorSigningKey(ctx context.Context, operatorID uuid.UUID) (*models.Operator, error) {
return nil, nil
}

// DeleteOperator ...
func (c *OperatorsController) DeleteOperator(ctx context.Context, id uuid.UUID) error {
return c.db.DeleteOperator(ctx, id)
}

// GetOperator ...
func (c *OperatorsController) GetOperator(ctx context.Context, id uuid.UUID) (*models.Operator, error) {
return c.db.GetOperator(ctx, id)
}

// ListOperator ...
func (c *OperatorsController) ListOperator(ctx context.Context, pagination models.Pagination[*models.Operator]) (*models.Pagination[*models.Operator], error) {
return c.db.ListOperator(ctx, pagination)
Expand Down
Loading

0 comments on commit 9283acf

Please sign in to comment.