Skip to content

WIP: init graphql support #14721

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

Closed
wants to merge 1 commit into from
Closed
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ coverage.all
/modules/templates/bindata.go
/modules/templates/bindata.go.hash

/modules/graphql/interfaces.go
/modules/graphql/model_gen.go

*.db
*.log

Expand Down
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ help:
@echo " - generate-license update license files"
@echo " - generate-gitignore update gitignore files"
@echo " - generate-swagger generate the swagger spec from code comments"
@echo " - generate-graphql generate the grapql code from defines"
@echo " - swagger-validate check if the swagger spec is valid"
@echo " - golangci-lint run golangci-lint linter"
@echo " - revive run revive linter"
Expand Down Expand Up @@ -273,6 +274,12 @@ errcheck:
@echo "Running errcheck..."
@errcheck $(GO_PACKAGES)

.PHONY: generate-graphql
generate-graphql:
cd modules/graphql && \
mod=vendor $(GO) run github.com/99designs/gqlgen genrate && \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't there be generate?

cd ../..

.PHONY: revive
revive:
GO111MODULE=on $(GO) run -mod=vendor build/lint.go -config .revive.toml -exclude=./vendor/... ./... || exit 1
Expand Down
3 changes: 3 additions & 0 deletions build.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,7 @@ import (

// for swagger
_ "github.com/go-swagger/go-swagger/cmd/swagger"

// for gqlgen
_ "github.com/99designs/gqlgen"
)
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
gitea.com/go-chi/captcha v0.0.0-20210110083842-e7696c336a1e
gitea.com/go-chi/session v0.0.0-20210108030337-0cb48c5ba8ee
gitea.com/lunny/levelqueue v0.3.0
github.com/99designs/gqlgen v0.13.0
github.com/NYTimes/gziphandler v1.1.1
github.com/PuerkitoBio/goquery v1.5.1
github.com/RoaringBitmap/roaring v0.5.5 // indirect
Expand All @@ -29,7 +30,7 @@ require (
github.com/ethantkoenig/rupture v1.0.0
github.com/gliderlabs/ssh v0.3.1
github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a // indirect
github.com/go-chi/chi v1.5.1
github.com/go-chi/chi v3.3.2+incompatible
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems incorrect, it would be ok to upgrade to v4

github.com/go-chi/cors v1.1.1
github.com/go-enry/go-enry/v2 v2.6.0
github.com/go-git/go-billy/v5 v5.0.0
Expand Down Expand Up @@ -97,6 +98,7 @@ require (
github.com/unknwon/paginater v0.0.0-20200328080006-042474bd0eae
github.com/unrolled/render v1.0.3
github.com/urfave/cli v1.22.5
github.com/vektah/gqlparser/v2 v2.1.0
github.com/willf/bitset v1.1.11 // indirect
github.com/xanzy/go-gitlab v0.42.0
github.com/yohcop/openid-go v1.0.0
Expand Down
36 changes: 36 additions & 0 deletions go.sum

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions modules/graphql/gqlgen.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Where should any generated models go?
model:
filename: model_gen.go
package: graphql

# Where should the generated server code go?
exec:
filename: interfaces.go
package: graphql

models:
ID:
model:
- github.com/99designs/gqlgen/graphql.Int64
9 changes: 9 additions & 0 deletions modules/graphql/mutation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package graphql

// Mutation Mutation port
type Mutation struct {
}
30 changes: 30 additions & 0 deletions modules/graphql/query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package graphql

import (
"context"
"fmt"

api "code.gitea.io/gitea/modules/context"
)

// Query query port
type Query struct {
}

// Viewer return current user message
func (v *Query) Viewer(ctx context.Context) (*User, error) {
apiCtx := ctx.Value("default_api_context").(*api.APIContext)
if apiCtx == nil {
return nil, fmt.Errorf("ctx is empty")
}

if !apiCtx.IsSigned {
return nil, fmt.Errorf("user is not login")
}

return convertUser(apiCtx.User, true), nil
}
127 changes: 127 additions & 0 deletions modules/graphql/repository.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package graphql

import (
"context"
"fmt"

"code.gitea.io/gitea/models"
api "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
repo_service "code.gitea.io/gitea/services/repository"
)

// CreateRepository Create a new repository
func (m *Mutation) CreateRepository(ctx context.Context, input CreateRepositoryInput) (*Repository, error) {
apiCtx := ctx.Value("default_api_context").(*api.APIContext)
if apiCtx == nil {
return nil, fmt.Errorf("ctx is empty")
}
if !apiCtx.IsSigned {
return nil, fmt.Errorf("user is not login")
}

var (
owner *models.User
err error
)
if input.OwnerID != nil {
if *input.OwnerID == apiCtx.User.ID {
owner = apiCtx.User
} else {
owner, err = models.GetUserByID(*input.OwnerID)
if err != nil {
if models.IsErrUserNotExist(err) {
return nil, fmt.Errorf("owner %v is not exist", *input.OwnerID)
}
log.Error("gql: GetUserByID: %v", err)
return nil, fmt.Errorf("Internal Server Error")
}
}
} else if input.Owner != nil {
if *input.Owner == apiCtx.User.Name {
owner = apiCtx.User
} else {
owner, err = models.GetUserByName(*input.Owner)
if err != nil {
if models.IsErrUserNotExist(err) {
return nil, fmt.Errorf("owner %s is not exist", *input.Owner)
}
log.Error("gql: GetUserByName: %v", err)
return nil, fmt.Errorf("Internal Server Error")
}
}
} else {
owner = apiCtx.User
}

if owner.ID != apiCtx.User.ID {
if !owner.IsOrganization() {
return nil, fmt.Errorf("not allow create repo for other user")
}
if !apiCtx.User.IsAdmin {
canCreate, err := owner.CanCreateOrgRepo(apiCtx.User.ID)
if err != nil {
log.Error("gql: CanCreateOrgRepo: %v", err)
return nil, fmt.Errorf("Internal Server Error")
} else if !canCreate {
return nil, fmt.Errorf("Given user is not allowed to create repository in organization %s", owner.Name)
}
}
}

opts := models.CreateRepoOptions{
Name: input.Name,
IsPrivate: input.Visibility == RepositoryVisibilityPrivate,
AutoInit: input.AutoInit != nil && *input.AutoInit,
DefaultBranch: input.DefaultBranch,
TrustModel: models.ToTrustModel(string(input.TrustModel)),
IsTemplate: input.Template != nil && *input.Template,
}

if input.AutoInit != nil && *input.AutoInit && input.Readme == nil {
opts.Readme = "Default"
}
if input.Description != nil {
opts.Description = *input.Description
}
if input.IssueLabels != nil {
opts.IssueLabels = *input.IssueLabels
}
if input.Gitignores != nil {
opts.Gitignores = *input.Gitignores
}
if input.License != nil {
opts.License = *input.License
}

repo, err := repo_service.CreateRepository(apiCtx.User, owner, opts)
if err != nil {
if models.IsErrRepoAlreadyExist(err) {
return nil, fmt.Errorf("The repository with the same name already exists")
} else if models.IsErrNameReserved(err) ||
models.IsErrNamePatternNotAllowed(err) {
return nil, err
}
log.Error("gql: CreateRepository: %v", err)
return nil, fmt.Errorf("Internal Server Error")
}

// reload repo from db to get a real state after creation
repo, err = models.GetRepositoryByID(repo.ID)
if err != nil {
log.Error("gql: GetRepositoryByID: %v", err)
return nil, fmt.Errorf("Internal Server Error")
}

return convertRepository(repo), nil
}

func convertRepository(repo *models.Repository) *Repository {
return &Repository{
Name: repo.Name,
}
}
23 changes: 23 additions & 0 deletions modules/graphql/resolver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
//go:generate go run -mod=vendor github.com/99designs/gqlgen genrate

package graphql

// This file will not be regenerated automatically.
//
// It serves as dependency injection for your app, add any dependencies you require here.

// Resolver resolver type define
type Resolver struct{}

// Query get query port
func (r *Resolver) Query() QueryResolver {
return &Query{}
}

// Mutation get mutation port
func (r *Resolver) Mutation() MutationResolver {
return &Mutation{}
}
92 changes: 92 additions & 0 deletions modules/graphql/schema.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Copyright 2021 The Gitea Authors. All rights reserved.
# Use of this source code is governed by a MIT-style
# license that can be found in the LICENSE file.

schema {
query: Query
mutation: Mutation
}

# query
type Query {
"get current user message"
viewer: User!
}

# mutation
type Mutation {
"Create a new repository"
createRepository(input: CreateRepositoryInput!) :Repository!
}

# models
type User {
"Identifies the date and time when the object was created"
createdAt: Time!
"Identifies the primary key from the database"
databaseId: ID!
"The user's publicly visible profile email"
email: String
"The username used to login"
login: String!
"The user's public profile name"
name: String!
}

# inputs

"the input options of CreateRepository"
input CreateRepositoryInput {
"The name of the new repository"
name :String!
"The name of the owner for the new repository"
owner: String
"The ID of the owner for the new repository"
ownerId: ID
"A short description of the new repository"
description: String
"Whether this repository should be marked as a template"
template: Boolean
"Indicates the repository's visibility level"
visibility: RepositoryVisibility!
"Label-Set to use"
issue_labels: String
"Whether the repository should be auto-intialized?"
auto_init: Boolean
"Gitignores to use"
gitignores: String
"License to use"
license: String
"Readme of the repository to create"
readme: String
"DefaultBranch of the repository"
default_branch: String!
"TrustModel of the repository"
trust_model: RepositoryTrustModel!
}

"A repository contains the content for a project"
type Repository {
"The name of the repository"
name: String!
}

# scalars
scalar Time

# enums

"The repository's visibility level"
enum RepositoryVisibility {
"The repository is visible only to those with explicit access"
PRIVATE
"The repository is visible to everyone"
PUBLIC
}

enum RepositoryTrustModel {
default
collaborator
committer
collaboratorcommitter
}
30 changes: 30 additions & 0 deletions modules/graphql/user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package graphql

import (
"time"

"code.gitea.io/gitea/models"
)

func convertUser(user *models.User, authed bool) *User {
if user == nil {
return nil
}

u := &User{
Login: user.Name,
Name: user.FullName,
DatabaseID: user.ID,
CreatedAt: time.Unix(int64(user.CreatedUnix), 0),
}

if !user.KeepEmailPrivate || authed {
u.Email = &user.Email
}

return u
}
Loading