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

Swagger users #33

Merged
merged 2 commits into from
Aug 31, 2023
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
1 change: 1 addition & 0 deletions browser/goliac-ui/src/components/DashboardApp.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<template>
<el-breadcrumb separator="/">
<el-breadcrumb-item :to="{ path: '/' }">Goliac</el-breadcrumb-item>
<el-breadcrumb-item :to="{ path: '/' }">dashboard</el-breadcrumb-item>
</el-breadcrumb>
<el-divider />
Expand Down
94 changes: 94 additions & 0 deletions docs/api_docs/bundle.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -94,12 +94,106 @@ paths:
description: generic error response
schema:
$ref: '#/definitions/error'
/users:
get:
tags:
- app
operationId: getUsers
description: Get all users
responses:
'200':
description: get list of users (organization or external)
schema:
$ref: '#/definitions/users'
default:
description: generic error response
schema:
$ref: '#/definitions/error'
/users/{userID}:
get:
tags:
- app
operationId: getUser
parameters:
- in: path
name: userID
description: user name
required: true
type: string
minLength: 1
description: Get user and associated teams and repos
responses:
'200':
description: get user details especially teams and repositories
schema:
$ref: '#/definitions/userDetails'
default:
description: generic error response
schema:
$ref: '#/definitions/error'
definitions:
health:
type: object
properties:
status:
type: string
users:
type: object
properties:
users:
type: array
items:
$ref: '#/definitions/user'
user:
type: object
properties:
name:
type: string
x-isnullable: false
external:
type: boolean
x-isnullable: false
userDetails:
type: object
properties:
teams:
type: array
items:
$ref: '#/definitions/team'
repositories:
type: array
items:
$ref: '#/definitions/repository'
repository:
type: object
properties:
name:
type: string
x-isnullable: false
public:
type: boolean
x-isnullable: false
x-omitempty: false
archived:
type: boolean
x-isnullable: false
x-omitempty: false
team:
type: object
properties:
name:
type: string
x-isnullable: false
owners:
type: array
items:
type: string
minLength: 1
members:
type: array
items:
type: string
minLength: 1
status:
type: object
properties:
Expand Down
7 changes: 7 additions & 0 deletions internal/engine/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ import (
* and mount it in memory
*/
type GoliacLocal interface {
GoliacLocalGit
GoliacLocalResources
}

type GoliacLocalGit interface {
Clone(accesstoken, repositoryUrl, branch string) error

// Return commits from tagname to HEAD
Expand All @@ -50,7 +55,9 @@ type GoliacLocal interface {

// Load and Validate from a local directory
LoadAndValidateLocal(fs afero.Fs, path string) ([]error, []entity.Warning)
}

type GoliacLocalResources interface {
Teams() map[string]*entity.Team // teamname, team definition
Repositories() map[string]*entity.Repository // reponame, repo definition
Users() map[string]*entity.User // github username, user definition
Expand Down
3 changes: 3 additions & 0 deletions internal/github/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ func (client *GitHubClientImpl) getAccessTokenForInstallation(jwt string) (strin
* },
*/
func (client *GitHubClientImpl) GetAccessToken() (string, error) {
logrus.Debugf("GetAccessToken(): client.tokenExpiration: %v", client.tokenExpiration)

if client.accessToken != "" && client.tokenExpiration.After(time.Now()) {
return client.accessToken, nil
Expand All @@ -372,6 +373,8 @@ func (client *GitHubClientImpl) GetAccessToken() (string, error) {
client.accessToken = accessToken
client.tokenExpiration = expiration

logrus.Debugf("GetAccessToken(): client.tokenExpiration: %v", client.tokenExpiration)

return accessToken, nil
}

Expand Down
4 changes: 2 additions & 2 deletions internal/goliac.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ type Goliac interface {
// flush remote cache
FlushCache()

GetLocal() engine.GoliacLocal
GetLocal() engine.GoliacLocalResources
}

type GoliacImpl struct {
Expand Down Expand Up @@ -72,7 +72,7 @@ func NewGoliacImpl() (Goliac, error) {
}, nil
}

func (g *GoliacImpl) GetLocal() engine.GoliacLocal {
func (g *GoliacImpl) GetLocal() engine.GoliacLocalResources {
return g.local
}

Expand Down
5 changes: 5 additions & 0 deletions internal/goliac_light.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import (
"github.com/spf13/afero"
)

/*
* This "version" of Goliac is here just to validate a local
* teams directory. It is mainly used for CI purpose when we need to validate
* a PR
*/
type GoliacLight interface {
// Validate a local teams directory
Validate(path string) error
Expand Down
125 changes: 121 additions & 4 deletions internal/goliac_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"time"

"github.com/Alayacare/goliac/internal/config"
"github.com/Alayacare/goliac/internal/entity"
"github.com/Alayacare/goliac/swagger_gen/models"
"github.com/Alayacare/goliac/swagger_gen/restapi"
"github.com/Alayacare/goliac/swagger_gen/restapi/operations"
Expand All @@ -23,20 +24,27 @@ import (
"github.com/sirupsen/logrus"
)

/*
* GoliacServer is here to run as a serve that
* - sync/reconciliate periodically
* - provide a REST API server
*/
type GoliacServer interface {
Serve()
GetLiveness(health.GetLivenessParams) middleware.Responder
GetReadiness(health.GetReadinessParams) middleware.Responder
PostFlushCache(app.PostFlushCacheParams) middleware.Responder
PostResync(app.PostResyncParams) middleware.Responder
GetStatus(app.GetStatusParams) middleware.Responder

GetUsers(app.GetUsersParams) middleware.Responder
GetUser(app.GetUserParams) middleware.Responder
}

type GoliacServerImpl struct {
goliac Goliac
applyMutex gosync.Mutex
// when the server has finished to load the local configuration
ready bool
goliac Goliac
applyMutex gosync.Mutex
ready bool // when the server has finished to load the local configuration
lastSyncTime *time.Time
lastSyncError error
syncInterval int // in seconds time remaining between 2 sync
Expand All @@ -49,6 +57,111 @@ func NewGoliacServer(goliac Goliac) GoliacServer {
}
}

func (g *GoliacServerImpl) GetUsers(app.GetUsersParams) middleware.Responder {
users := models.Users{
Users: make([]*models.User, 0),
}
local := g.goliac.GetLocal()
for username := range local.Users() {
u := models.User{
External: false,
Name: username,
}
users.Users = append(users.Users, &u)
}
for username := range local.ExternalUsers() {
u := models.User{
External: true,
Name: username,
}
users.Users = append(users.Users, &u)
}
return app.NewGetUsersOK().WithPayload(&users)
}

func (g *GoliacServerImpl) GetUser(params app.GetUserParams) middleware.Responder {
userdetails := models.UserDetails{
Teams: make([]*models.Team, 0),
Repositories: make([]*models.Repository, 0),
}

// [teamname]team
userTeams := make(map[string]*models.Team)
local := g.goliac.GetLocal()
for teamname, team := range local.Teams() {
for _, owner := range team.Data.Owners {
if owner == params.UserID {
team := models.Team{
Name: teamname,
Members: team.Data.Members,
Owners: team.Data.Owners,
}
userTeams[teamname] = &team
break
}
}
for _, member := range team.Data.Members {
if member == params.UserID {
team := models.Team{
Name: teamname,
Members: team.Data.Members,
Owners: team.Data.Owners,
}
userTeams[teamname] = &team
break
}
}
}

for _, t := range userTeams {
userdetails.Teams = append(userdetails.Teams, t)
}

// let's sort repo per team
teamRepo := make(map[string]map[string]*entity.Repository)
for _, repo := range local.Repositories() {
if repo.Owner != nil {
if _, ok := teamRepo[*repo.Owner]; !ok {
teamRepo[*repo.Owner] = make(map[string]*entity.Repository)
}
teamRepo[*repo.Owner][repo.Metadata.Name] = repo
}
for _, r := range repo.Data.Readers {
if _, ok := teamRepo[r]; !ok {
teamRepo[r] = make(map[string]*entity.Repository)
}
teamRepo[r][repo.Metadata.Name] = repo
}
for _, w := range repo.Data.Writers {
if _, ok := teamRepo[w]; !ok {
teamRepo[w] = make(map[string]*entity.Repository)
}
teamRepo[w][repo.Metadata.Name] = repo
}
}

// [reponame]repo
userRepos := make(map[string]*entity.Repository)
for _, team := range userdetails.Teams {
if repositories, ok := teamRepo[team.Name]; ok {
for n, r := range repositories {
userRepos[n] = r
}
}
}

for _, r := range userRepos {
repo := models.Repository{
Name: r.Metadata.Name,
Public: r.Data.IsPublic,
Archived: r.Data.IsArchived,
}
userdetails.Repositories = append(userdetails.Repositories, &repo)
}

return app.NewGetUserOK().WithPayload(&userdetails)
}

func (g *GoliacServerImpl) GetStatus(app.GetStatusParams) middleware.Responder {
s := models.Status{
LastSyncError: "",
Expand Down Expand Up @@ -172,6 +285,10 @@ func (g *GoliacServerImpl) StartRESTApi() (*restapi.Server, error) {
api.AppPostFlushCacheHandler = app.PostFlushCacheHandlerFunc(g.PostFlushCache)
api.AppPostResyncHandler = app.PostResyncHandlerFunc(g.PostResync)
api.AppGetStatusHandler = app.GetStatusHandlerFunc(g.GetStatus)

api.AppGetUsersHandler = app.GetUsersHandlerFunc(g.GetUsers)
api.AppGetUserHandler = app.GetUserHandlerFunc(g.GetUser)

server := restapi.NewServer(api)

server.Host = config.Config.SwaggerHost
Expand Down
Loading