├── .env.example ├── .github └── workflows │ └── test.yaml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Makefile ├── README.md ├── application ├── repositories │ ├── challenge_repository.go │ ├── challenge_repository_test.go │ ├── user_repository.go │ └── user_repository_test.go └── usecases │ ├── challenge_usecase.go │ ├── login.go │ ├── user_usecase.go │ └── user_usercase_test.go ├── docker-compose.yml ├── domain ├── author.go ├── author_test.go ├── base.go ├── challenge.go ├── challenge_file.go ├── challenge_file_test.go ├── user.go └── user_test.go ├── framework ├── cmd │ └── server │ │ └── main.go ├── pb │ ├── challenge_message.pb.go │ └── user_message.pb.go ├── servers │ ├── challenge_server.go │ ├── user_server.go │ └── user_server_test.go └── utils │ ├── db.go │ └── utils.go ├── go.mod ├── go.sum ├── proto ├── challenge_message.proto └── user_message.proto └── sonar-project.properties /.env.example: -------------------------------------------------------------------------------- 1 | dbType="postgres" 2 | dsn="dbname=codeedu sslmode=disable user=postgres password=root" 3 | 4 | dbTypeTest="sqlite3" 5 | dsnTest=":memory:" 6 | 7 | env="dev" 8 | debug=true 9 | AutoMigrateDb=true -------------------------------------------------------------------------------- /.github/workflows/test.yaml: -------------------------------------------------------------------------------- 1 | on: [push, pull_request] 2 | name: Test 3 | jobs: 4 | test: 5 | strategy: 6 | matrix: 7 | go-version: [1.14.x] 8 | platform: [ubuntu-latest] 9 | runs-on: ${{ matrix.platform }} 10 | steps: 11 | - name: Install Go 12 | uses: actions/setup-go@v1 13 | with: 14 | go-version: ${{ matrix.go-version }} 15 | 16 | - name: Checkout code 17 | uses: actions/checkout@v2 18 | 19 | - name: Creating .env 20 | uses: canastro/copy-file-action@master 21 | with: 22 | source: ".env.example" 23 | target: ".env" 24 | 25 | - name: Test 26 | run: go test ./... 27 | 28 | - name: SonarCloud Scan 29 | uses: sonarsource/sonarcloud-github-action@master 30 | env: 31 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 32 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .pgdata 2 | .idea 3 | .env 4 | .DS_Store -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at fabianoleittes@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Guia de contribuição do projeto 2 | 3 | ## Tabela de conteúdo 4 | 5 | - [Primeiros Passos](#primeiros-passos) 6 | - [Código de conduta](#código-de-conduta) 7 | - [Como posso ajudar?](#como-posso-ajudar) 8 | - [Documentação](#documentação) 9 | - [Problemas](#problemas) 10 | - [Enviando um problema](#enviando-um-problema) 11 | - [Feedback](#feedback) 12 | - [Código](#código) 13 | - [Ambiente de desenvolvimento](#ambiente-de-desenvolvimento) 14 | - [Convenção de Commits](#convenção-de-commits) 15 | - [Por que todas essas regras?](#porque-todas-essas-regras) 16 | - [Enviando um pull request](#enviando-um-pull-request) 17 | 18 | ## Primeiros Passos 19 | 20 | Primeiramente, gostaríamos de agradecer por você dedicar um tempo para contribuir e fazer deste um projeto melhor.. 21 | 22 | Aqui temos um conjunto de instruções e diretrizes para reduzir mal-entendidos e tornar o processo de contribuição para o `codeedu-plataforma-desafios` o mais suave possível. 23 | 24 | Esperamos que este guia ajude a torne claro o processo de contribuição e responda a quaisquer perguntas que você possa ter. 25 | 26 | ### Código de conduta 27 | 28 | Esperamos que os participantes do projeto cumpram nosso Código de Conduta. Você pode verificar o [texto completo](https://github.com/codeedu/codeedu-plataforma-desafios/blob/master/CODE_OF_CONDUCT.md) para entender o tipo de conduta que esperamos e quais ações serão e não serão toleradas. 29 | 30 | Ao participar deste projeto, você concorda em cumprir seus termos. 31 | 32 | ## Como posso ajudar? 33 | 34 | Aqui estão algumas maneiras pelas quais você pode ajudar, juntamente com algumas diretrizes. 35 | 36 | ### Documentação 37 | 38 | Como usuário de `codeedu-plataforma-desafios`, você é o candidato perfeito para nos ajudar a melhorar nossa documentação. 39 | 40 | Erros de digitação, erros, falta de exemplos e/ou explicações e assim por diante, são apenas alguns exemplos de coisas que podem ser corrigidas e/ou aprimoradas. 41 | 42 | Você pode até fazer melhorias neste guia. :) 43 | 44 | Ao documentar, tente manter as coisas simples e claras. 45 | 46 | ### Problemas 47 | 48 | Alguns problemas são criados com informações ausentes, sem um modelo, não reproduzíveis ou simples inválido. 49 | 50 | Você pode torná-los mais fáceis de entender e resolver. 51 | 52 | #### Enviando um problema 53 | 54 | - Procure problemas semelhantes antes de abrir um novo; 55 | - Use um dos modelos de problemas correspondentes; 56 | - Use um título claro e descritivo; 57 | - Inclua o máximo de informações possível, preenchendo o modelo de problema fornecido; 58 | - Na maioria das vezes, a melhor maneira de relatar um problema é a falha no teste. 59 | 60 | ### Feedback 61 | 62 | Quanto mais feedback, melhor! Estamos sempre procurando mais sugestões e opiniões sobre discussões. Essa é uma boa oportunidade para influenciar a direção futura desta ferramenta. 63 | 64 | Isso inclui o envio de uma sugestão de aprimoramento, incluindo recursos completamente novos e pequenas melhorias na funcionalidade existente. 65 | 66 | ### Código 67 | 68 | Você pode usar `issue labels` para descobrir problemas com os quais você poderia ajudar: 69 | 70 | - [`bug` issues](https://github.com/codeedu/codeedu-plataforma-desafios/labels/bug) são erros conhecidos que gostaríamos de corrigir; 71 | - [`enhancement` issues](https://github.com/codeedu/codeedu-plataforma-desafios/labels/enhancement) são recursos que estamos abertos a incluir. 72 | 73 | Quando você vir um problema(`issue`) que já está atribuído, verifique se já não há alguém trabalhando nele (talvez tente perguntar no problema(`issue`). Isso é para evitar trabalho desnecessário para todos os envolvidos. 74 | 75 | #### Ambiente de desenvolvimento 76 | 77 | Ao desenvolver, prefira usar **Go** ≥ 1,14. Escrever código com as últimas versões estáveis ​​do Go nos permite usar novas ferramentas de desenvolvedor. 78 | 79 | Depois de [clonar o repositório](https://help.github.com/articles/cloning-a-repository/), para subir a aplicação `server` você precisa navegar até sua pasta. 80 | 81 | **server** (/codeedu-plataforma-desafios/framework/cmd/server) 82 | 83 | $ go run main.go 84 | 85 | **Despendências:** 86 | Você precisa subir a base de dados usando o `docker` para isso, basta execultar o comando abaixo. 87 | 88 | $ docker-compose up 89 | 90 | #### Convenção de Commits 91 | 92 | Essa convenção usa o [conventionalcommits.org](https://www.conventionalcommits.org/en/v1.0.0/) 93 | 94 | #### Resumo 95 | 96 | A especificação do Conventional Commits é uma convenção simples para utilizar nas mensagens de commit. Ela define um conjunto de regras para criar um histórico de commit explícito, o que facilita a criação de ferramentas automatizadas. Esta convenção segue o [SemVer](https://semver.org/), descrevendo os recursos, correções e modificações que quebram a compatibilidade nas mensagens de commit. 97 | 98 | A mensagem do commit deve ser estruturada da seguinte forma: 99 | 100 | ``` 101 | [optional scope]: 102 | 103 | [optional body] 104 | 105 | [optional footer(s)] 106 | ``` 107 | 108 | O commit contém os seguintes elementos estruturais, para comunicar a intenção ao utilizador da sua biblioteca: 109 | 110 | **fix:** um commit do tipo fix soluciona um problema na sua base de código (isso se correlaciona com `PATCH` do versionamento semântico). 111 | **feat:** um commit do tipo feat inclui um novo recurso na sua base de código (isso se correlaciona com `MINOR` do versionamento semântico). 112 | **BREAKING CHANGE:** um commit que contém o texto BREAKING CHANGE:, no começo do texto do corpo opcional ou do rodapé opcional, inclui uma modificação que quebra a compatibilidade da API (isso se correlaciona com `MAJOR` do versionamento semântico). Uma BREAKING CHANGE pode fazer parte de commits de qualquer tipo. 113 | Outros: tipos adicionais são permitidos além de fix: e feat:, por exemplo [@commitlint/config-conventional](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional) (baseado na Convenção do Angular) recomenda-se `chore:`, `docs:`, `style:`, `refactor:`, `perf:`, `test:`, entre outros. 114 | 115 | ##### [Exemplos de commits](https://www.conventionalcommits.org/pt-br/v1.0.0-beta.4/#exemplos) 116 | 117 | ##### [mais informações](https://www.conventionalcommits.org/en/v1.0.0/) 118 | 119 | ## Enviando um pull request 120 | 121 | Antes de enviar um `pull request`, verifique se o seguinte foi feito: 122 | 123 | - Está segguindo o [GitHub Flow](https://guides.github.com/introduction/flow/) 124 | - Está segguindo o [5 Useful Tips For A Better Commit Message](https://robots.thoughtbot.com/5-useful-tips-for-a-better-commit-message) artigo e o post [How to Write a Git Commit Message](http://chris.beams.io/posts/git-commit/) post. 125 | - Está segguindo o [Linking a pull request to an issue](https://help.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue) 126 | 127 | - [Fork](https://help.github.com/en/articles/fork-a-repo) o repositório e crie seu branch a partir do `master`. 128 | - Exemplo: `feature/my-awesome-feature` ou `fix/annoying-bug`; 129 | - Se você corrigiu um bug ou adicionou um código que deve ser testado, **adicione testes** por favor; 130 | - Garantir que o conjunto de testes seja aprovado; 131 | - Garanta que seu commit seja validado; 132 | - Execute `go test ./...` para rodar todos os testes; 133 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | gen: 2 | protoc --proto_path=proto proto/*.proto --go_out=plugins=grpc:framework/pb 3 | 4 | clean: 5 | rm pb/*.go 6 | 7 | server: 8 | go run framework/cmd/server/main.go -port 8080 9 | 10 | client: 11 | go run framework/cmd/client/main.go -address 0.0.0.0:8080 12 | 13 | test: 14 | go test -cover -race ./... 15 | 16 | .PHONY: gen clean server client test -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Plataforma de desafios da Code.education 2 | 3 | ![Test](https://github.com/codeedu/codeedu-plataforma-desafios/workflows/Test/badge.svg?branch=master) 4 | 5 | ## Objetivo 6 | 7 | Esse projeto tem o objetivo de desafiar desenvolvedores a sairem da zona de conforto, aprenderem uma nova linguagem de programação, bem como conceitos modernos e fundamentais nos dias de hoje. 8 | 9 | ## Dinâmica do projeto 10 | 11 | Para cada fase do projeto, um vídeo será gravado explicando os principais conceitos das novas implementações, bem como as nuances da linguagem Go. 12 | 13 | Os vídeos estarão disponibilizados no [canal Full Cycle no Youtube](http://youtube.com/fullcycle). 14 | 15 | Na seção "Issues" desse repositório você encontrará tarefas para melhorias e funcionalidades que deverão ser implementadas. 16 | 17 | ## Para testar a execução do server 18 | 19 | Para testar os serviços disponibilizados pelo "server", recomendamos a utilização do "evans", um client gRPC desenvolvido em Go. 20 | 21 | Exemplo: 22 | 23 | ```bash 24 | evans -r -p 8080 25 | ``` 26 | 27 | ## Contribuindo 28 | 29 | Veja como contribuir [aqui](https://github.com/codeedu/codeedu-plataforma-desafios/blob/master/CONTRIBUTING.md) 30 | 31 | ## Licença 32 | 33 | Esse projeto é open source, aceitará contribuições qualquer natureza para que a plataforma de desafios seja criada e está licenciado sob a [MIT license](https://opensource.org/licenses/MIT). 34 | -------------------------------------------------------------------------------- /application/repositories/challenge_repository.go: -------------------------------------------------------------------------------- 1 | package repositories 2 | 3 | import ( 4 | "fmt" 5 | "github.com/codeedu/codeedu-plataforma-desafios/domain" 6 | "github.com/jinzhu/gorm" 7 | ) 8 | 9 | type ChallengeRepository interface { 10 | Insert(challenge *domain.Challenge) (*domain.Challenge, error) 11 | Find(id string) (*domain.Challenge, error) 12 | FindAll(order string) ([]domain.Challenge, error) 13 | } 14 | 15 | type ChallengeRepositoryDb struct { 16 | Db *gorm.DB 17 | } 18 | 19 | func (repo ChallengeRepositoryDb) Insert(challenge *domain.Challenge) (*domain.Challenge, error) { 20 | 21 | err := repo.Db.Create(challenge).Error 22 | 23 | if err != nil { 24 | return nil, err 25 | } 26 | return challenge, nil 27 | } 28 | 29 | func (repo ChallengeRepositoryDb) Find(id string) (*domain.Challenge, error) { 30 | 31 | var challenge domain.Challenge 32 | repo.Db.Preload("ChallengeFiles").First(&challenge, "id = ?", id) 33 | 34 | if challenge.ID == "" { 35 | return nil, fmt.Errorf("Challenge does not exist") 36 | } 37 | 38 | return &challenge, nil 39 | } 40 | 41 | func (repo ChallengeRepositoryDb) FindAll(order string) ([]domain.Challenge, error) { 42 | 43 | var challenges []domain.Challenge 44 | repo.Db.Preload("ChallengeFiles").Find(&challenges).Order(order) 45 | 46 | return challenges, nil 47 | } 48 | -------------------------------------------------------------------------------- /application/repositories/challenge_repository_test.go: -------------------------------------------------------------------------------- 1 | package repositories_test 2 | 3 | import ( 4 | "github.com/bxcodec/faker/v3" 5 | "github.com/codeedu/codeedu-plataforma-desafios/application/repositories" 6 | "github.com/codeedu/codeedu-plataforma-desafios/domain" 7 | "github.com/codeedu/codeedu-plataforma-desafios/framework/utils" 8 | "github.com/stretchr/testify/require" 9 | "testing" 10 | ) 11 | 12 | func TestChallengeRepositoryDb_Insert(t *testing.T) { 13 | db := utils.ConnectDB("test") 14 | defer db.Close() 15 | 16 | challenge := domain.NewChallenge() 17 | challenge.Title = faker.Word() 18 | challenge.Slug = faker.Word() 19 | challenge.Description = faker.Sentence() 20 | challenge.Tags = faker.Word() 21 | challenge.Requirements = faker.Sentence() 22 | challenge.Level = faker.Word() 23 | 24 | require.Nil(t, challenge.Valid()) 25 | 26 | repo := repositories.ChallengeRepositoryDb{Db: db} 27 | repo.Insert(challenge) 28 | 29 | c, err := repo.Find(challenge.ID) 30 | require.NotEmpty(t, c.ID) 31 | require.Equal(t, c.ID, challenge.ID) 32 | require.Nil(t, err) 33 | } 34 | 35 | func TestChallengeRepositoryDb_InsertWithChallengeFiles(t *testing.T) { 36 | db := utils.ConnectDB("test") 37 | defer db.Close() 38 | 39 | challenge := domain.NewChallenge() 40 | challenge.Title = faker.Word() 41 | challenge.Slug = faker.Word() 42 | challenge.Description = faker.Sentence() 43 | challenge.Tags = faker.Word() 44 | challenge.Requirements = faker.Sentence() 45 | challenge.Level = faker.Word() 46 | require.Nil(t, challenge.Valid()) 47 | 48 | file1, err := domain.NewChallengeFile("test.txt", "http://google.com/test.txt") 49 | file1.ChallengeID = challenge.ID 50 | require.Nil(t, file1.Valid()) 51 | 52 | file2, err := domain.NewChallengeFile("test2.txt", "http://google.com/test2.txt") 53 | file2.ChallengeID = challenge.ID 54 | require.Nil(t, file2.Valid()) 55 | 56 | var files []*domain.ChallengeFile 57 | files = append(files, file1) 58 | files = append(files, file2) 59 | 60 | challenge.ChallengeFiles = files 61 | 62 | repo := repositories.ChallengeRepositoryDb{Db: db} 63 | repo.Insert(challenge) 64 | 65 | c, err := repo.Find(challenge.ID) 66 | require.NotEmpty(t, c.ID) 67 | require.Equal(t, c.ID, challenge.ID) 68 | require.Nil(t, err) 69 | 70 | require.Equal(t, 2, len(c.ChallengeFiles)) 71 | } 72 | -------------------------------------------------------------------------------- /application/repositories/user_repository.go: -------------------------------------------------------------------------------- 1 | package repositories 2 | 3 | import ( 4 | "fmt" 5 | "github.com/codeedu/codeedu-plataforma-desafios/domain" 6 | "github.com/jinzhu/gorm" 7 | ) 8 | 9 | type UserRepository interface { 10 | Insert(user *domain.User) (*domain.User, error) 11 | Find(email string) (*domain.User, error) 12 | } 13 | 14 | type UserRepositoryDb struct { 15 | Db *gorm.DB 16 | } 17 | 18 | func (repo UserRepositoryDb) Insert(user *domain.User) (*domain.User, error) { 19 | 20 | err := repo.Db.Create(user).Error 21 | 22 | if err != nil { 23 | return nil, err 24 | } 25 | 26 | return user, nil 27 | } 28 | 29 | func (repo UserRepositoryDb) Find(email string) (*domain.User, error) { 30 | 31 | var user domain.User 32 | repo.Db.First(&user, "email = ?", email) 33 | 34 | if user.Token == "" { 35 | return nil, fmt.Errorf("User does not exist") 36 | } 37 | 38 | return &user, nil 39 | 40 | } 41 | -------------------------------------------------------------------------------- /application/repositories/user_repository_test.go: -------------------------------------------------------------------------------- 1 | package repositories_test 2 | 3 | import ( 4 | "github.com/asaskevich/govalidator" 5 | "github.com/bxcodec/faker/v3" 6 | "github.com/codeedu/codeedu-plataforma-desafios/application/repositories" 7 | "github.com/codeedu/codeedu-plataforma-desafios/domain" 8 | "github.com/codeedu/codeedu-plataforma-desafios/framework/utils" 9 | "github.com/stretchr/testify/require" 10 | "log" 11 | "testing" 12 | ) 13 | 14 | func TestUserRepositoryDb_Find(t *testing.T) { 15 | db := utils.ConnectDB("test") 16 | defer db.Close() 17 | 18 | repo := repositories.UserRepositoryDb{Db: db} 19 | newUser, err := domain.NewUser(faker.Name(), faker.Email(), "123") 20 | 21 | if err != nil { 22 | log.Fatalf("%v", err) 23 | } 24 | repo.Insert(newUser) 25 | 26 | res, _ := repo.Find(newUser.Email) 27 | 28 | require.NotEmpty(t, res.Token) 29 | require.True(t, govalidator.IsUUIDv4(res.Token)) 30 | 31 | } 32 | -------------------------------------------------------------------------------- /application/usecases/challenge_usecase.go: -------------------------------------------------------------------------------- 1 | package usecases 2 | 3 | import ( 4 | "github.com/codeedu/codeedu-plataforma-desafios/application/repositories" 5 | "github.com/codeedu/codeedu-plataforma-desafios/domain" 6 | ) 7 | 8 | type ChallengeUseCase struct { 9 | ChallengeRepository repositories.ChallengeRepository 10 | } 11 | 12 | func (c *ChallengeUseCase) Create(challenge *domain.Challenge) (*domain.Challenge, error) { 13 | 14 | res, err := c.ChallengeRepository.Insert(challenge) 15 | 16 | if err != nil { 17 | return res, err 18 | } 19 | 20 | return res, nil 21 | } 22 | -------------------------------------------------------------------------------- /application/usecases/login.go: -------------------------------------------------------------------------------- 1 | package usecases 2 | 3 | import ( 4 | "io/ioutil" 5 | "os" 6 | ) 7 | 8 | type Login struct{} 9 | 10 | func (login Login) Auth(email string, password string) string { 11 | token := "123" 12 | 13 | token, err := login.persistToken(token) 14 | if err != nil { 15 | panic(err) 16 | } 17 | return token 18 | } 19 | 20 | func (login Login) persistToken(token string) (string, error) { 21 | 22 | home, err := os.UserHomeDir() 23 | if err != nil { 24 | panic(err) 25 | } 26 | 27 | path := home + "/.codeedu" 28 | err = os.Mkdir(path, os.ModePerm) 29 | 30 | if err != nil { 31 | panic(err) 32 | } 33 | 34 | content := []byte(token) 35 | err = ioutil.WriteFile(path+"/token", content, 0644) 36 | if err != nil { 37 | panic(err) 38 | } 39 | 40 | return token, nil 41 | } 42 | -------------------------------------------------------------------------------- /application/usecases/user_usecase.go: -------------------------------------------------------------------------------- 1 | package usecases 2 | 3 | import ( 4 | "fmt" 5 | "github.com/codeedu/codeedu-plataforma-desafios/application/repositories" 6 | "github.com/codeedu/codeedu-plataforma-desafios/domain" 7 | ) 8 | 9 | type UserUseCase struct { 10 | UserRepository repositories.UserRepository 11 | } 12 | 13 | func (u *UserUseCase) Create(user *domain.User) (*domain.User, error) { 14 | 15 | user, err := u.UserRepository.Insert(user) 16 | 17 | if err != nil { 18 | return user, err 19 | } 20 | 21 | return user, nil 22 | } 23 | 24 | func (u *UserUseCase) Auth(email string, password string) (*domain.User, error) { 25 | 26 | user, err := u.UserRepository.Find(email) 27 | 28 | if err != nil { 29 | return nil, fmt.Errorf("The password is invalid for the user: %v", email) 30 | } 31 | 32 | if user.IsCorrectPassword(password) { 33 | return user, nil 34 | } 35 | 36 | return nil, fmt.Errorf("The password is invalid for the user: %v", email) 37 | 38 | } 39 | -------------------------------------------------------------------------------- /application/usecases/user_usercase_test.go: -------------------------------------------------------------------------------- 1 | package usecases_test 2 | 3 | import ( 4 | "github.com/bxcodec/faker/v3" 5 | "github.com/codeedu/codeedu-plataforma-desafios/application/repositories" 6 | "github.com/codeedu/codeedu-plataforma-desafios/application/usecases" 7 | "github.com/codeedu/codeedu-plataforma-desafios/domain" 8 | "github.com/codeedu/codeedu-plataforma-desafios/framework/utils" 9 | "github.com/jinzhu/gorm" 10 | "github.com/stretchr/testify/require" 11 | "testing" 12 | ) 13 | 14 | var db *gorm.DB 15 | 16 | func TestLogin_Auth(t *testing.T) { 17 | db = utils.ConnectDB("test") 18 | 19 | repo := repositories.UserRepositoryDb{Db: db} 20 | email := faker.Email() 21 | password := faker.Password() 22 | 23 | newUser, err := domain.NewUser(faker.Name(), email, password) 24 | repo.Insert(newUser) 25 | 26 | userUserCase := usecases.UserUseCase{UserRepository: repo} 27 | _, err = userUserCase.Auth(email, password) 28 | require.Nil(t, err) 29 | } 30 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | db: 5 | image: postgres:9.4 6 | restart: always 7 | tty: true 8 | volumes: 9 | - .pgdata:/var/lib/postgresql/data 10 | environment: 11 | - POSTGRES_PASSWORD=root 12 | - POSTGRES_DB=codeedu 13 | ports: 14 | - "5432:5432" -------------------------------------------------------------------------------- /domain/author.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "github.com/asaskevich/govalidator" 5 | uuid "github.com/satori/go.uuid" 6 | "time" 7 | ) 8 | 9 | type Author struct { 10 | Base `valid:"required"` 11 | Name string `json:"name" valid:"notnull" gorm:"type:varchar(255)"` 12 | Email string `json:"email" valid:"email" gorm:"type:varchar(255)"` 13 | Picture string `json:"picture" valid:"-" gorm:"type:varchar(255)"` 14 | Github string `json:"picture" valid:"-" gorm:"type:varchar(255)"` 15 | } 16 | 17 | func NewAuthor(name string, email string) (*Author, error) { 18 | 19 | author := Author{ 20 | Name: name, 21 | Email: email, 22 | } 23 | 24 | author.ID = uuid.NewV4().String() 25 | author.CreatedAt = time.Now() 26 | 27 | err := author.isValid() 28 | 29 | if err != nil { 30 | return nil, err 31 | } 32 | 33 | return &author, nil 34 | } 35 | 36 | func (author *Author) isValid() (error) { 37 | 38 | _, err := govalidator.ValidateStruct(author) 39 | 40 | if err != nil { 41 | return err 42 | } 43 | 44 | return nil 45 | } 46 | -------------------------------------------------------------------------------- /domain/author_test.go: -------------------------------------------------------------------------------- 1 | package domain_test 2 | 3 | import ( 4 | "github.com/bxcodec/faker/v3" 5 | "github.com/codeedu/codeedu-plataforma-desafios/domain" 6 | "github.com/stretchr/testify/require" 7 | "testing" 8 | ) 9 | 10 | func TestNewAuthor(t *testing.T) { 11 | 12 | name := faker.Name() 13 | email := faker.Email() 14 | 15 | author, err := domain.NewAuthor(name, email) 16 | 17 | require.Nil(t, err) 18 | require.Equal(t, author.Name, name) 19 | require.Equal(t, author.Email, email) 20 | 21 | email = "invalid-email" 22 | 23 | author, err = domain.NewAuthor(name, email) 24 | require.NotNil(t, err) 25 | require.Nil(t, author) 26 | 27 | author, err = domain.NewAuthor("", faker.Email()) 28 | require.NotNil(t, err) 29 | require.Nil(t, author) 30 | } 31 | -------------------------------------------------------------------------------- /domain/base.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "github.com/asaskevich/govalidator" 5 | "time" 6 | ) 7 | 8 | func init() { 9 | govalidator.SetFieldsRequiredByDefault(true) 10 | } 11 | 12 | type Base struct { 13 | ID string `json:"id" gorm:"type:uuid;primary_key" valid:"uuid"` 14 | CreatedAt time.Time `json:"created_at" valid:"-"` 15 | UpdatedAt time.Time `json:"updated_at" valid:"-"` 16 | //DeletedAt time.Time `json:"deleted_at" valid:"-" sql:"index"` 17 | } -------------------------------------------------------------------------------- /domain/challenge.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "github.com/asaskevich/govalidator" 5 | uuid "github.com/satori/go.uuid" 6 | "time" 7 | ) 8 | 9 | type Challenge struct { 10 | Base `valid:"required"` 11 | Title string `json:"title" valid:"notnull" gorm:"type:varchar(255)"` 12 | Slug string `json:"slug" valid:"notnull" gorm:"type:varchar(255)"` 13 | Description string `json:"description" valid:"notnull" gorm:"type:text"` 14 | Tags string `json:"tags" valid:"notnull" gorm:"type:varchar(255)"` 15 | Requirements string `json:"requirements" valid:"notnull" gorm:"type:varchar(255)"` 16 | Level string `json:"level" valid:"notnull" gorm:"type:varchar(255)"` 17 | ChallengeFiles []*ChallengeFile `gorm:"ForeignKey:ChallengeID" valid:"-"` 18 | } 19 | 20 | func NewChallenge() *Challenge { 21 | return &Challenge{} 22 | } 23 | 24 | func (challenge *Challenge) Valid() error { 25 | 26 | challenge.ID = uuid.NewV4().String() 27 | challenge.CreatedAt = time.Now() 28 | 29 | _, err := govalidator.ValidateStruct(challenge) 30 | 31 | if err != nil { 32 | return err 33 | } 34 | 35 | return nil 36 | 37 | } -------------------------------------------------------------------------------- /domain/challenge_file.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "github.com/asaskevich/govalidator" 5 | uuid "github.com/satori/go.uuid" 6 | "time" 7 | ) 8 | 9 | type ChallengeFile struct { 10 | Base `valid:"required"` 11 | Name string `json:"name" valid:"notnull" gorm:"type:varchar(255)"` 12 | URL string `json:"name" valid:"url" gorm:"type:varchar(255)"` 13 | ChallengeID string `gorm:"column:challenge_id;type:uuid;not null" valid:"-"` 14 | Challenge Challenge `valid:"-"` 15 | } 16 | 17 | func NewChallengeFile(name string, url string) (*ChallengeFile, error) { 18 | 19 | cfile := ChallengeFile{ 20 | Name: name, 21 | URL: url, 22 | } 23 | 24 | cfile.ID = uuid.NewV4().String() 25 | cfile.CreatedAt = time.Now() 26 | 27 | err := cfile.Valid() 28 | 29 | if err != nil { 30 | return nil, err 31 | } 32 | 33 | return &cfile, nil 34 | } 35 | 36 | func (cfile *ChallengeFile) Valid() (error) { 37 | 38 | _, err := govalidator.ValidateStruct(cfile) 39 | 40 | if err != nil { 41 | return err 42 | } 43 | 44 | return nil 45 | } 46 | -------------------------------------------------------------------------------- /domain/challenge_file_test.go: -------------------------------------------------------------------------------- 1 | package domain_test 2 | 3 | import ( 4 | "github.com/bxcodec/faker/v3" 5 | "github.com/codeedu/codeedu-plataforma-desafios/domain" 6 | "github.com/stretchr/testify/require" 7 | "testing" 8 | ) 9 | 10 | func TestNewChallengeFile(t *testing.T) { 11 | 12 | fileName := "text.txt" 13 | fileURL := faker.URL() + "/" + fileName 14 | 15 | cfile, err := domain.NewChallengeFile(fileName, fileURL) 16 | 17 | require.Equal(t, cfile.Name, fileName) 18 | require.Nil(t, err) 19 | 20 | fileName = "text.txt" 21 | fileURL = "ivalid-url" 22 | 23 | cfile, err = domain.NewChallengeFile(fileName, fileURL) 24 | 25 | require.Nil(t, cfile) 26 | require.NotNil(t, err) 27 | 28 | fileName = "" 29 | fileURL = "ivalid-url" 30 | 31 | cfile, err = domain.NewChallengeFile(fileName, fileURL) 32 | 33 | require.Nil(t, cfile) 34 | require.NotNil(t, err) 35 | 36 | } 37 | -------------------------------------------------------------------------------- /domain/user.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "github.com/asaskevich/govalidator" 5 | uuid "github.com/satori/go.uuid" 6 | "golang.org/x/crypto/bcrypt" 7 | "time" 8 | ) 9 | 10 | func init() { 11 | govalidator.SetFieldsRequiredByDefault(true) 12 | } 13 | 14 | type User struct { 15 | Base `valid:"required"` 16 | Name string `json:"name" gorm:"type:varchar(255)" valid:"notnull"` 17 | Email string `json:"email" gorm:"type:varchar(255);unique_index" valid:"notnull,email"` 18 | Password string `json:"-" gorm:"type:varchar(255)" valid:"notnull"` 19 | Token string `json:"token" gorm:"type:varchar(255);unique_index" valid:"notnull,uuid"` 20 | } 21 | 22 | func NewUser(name string, email string, password string) (*User, error) { 23 | user := &User{ 24 | Name: name, 25 | Email: email, 26 | Password: password, 27 | } 28 | 29 | err := user.Prepare() 30 | 31 | if err != nil { 32 | return nil, err 33 | } 34 | 35 | return user, nil 36 | } 37 | 38 | func (user *User) Prepare() error { 39 | 40 | password, err := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost) 41 | 42 | if err != nil { 43 | return err 44 | } 45 | 46 | user.ID = uuid.NewV4().String() 47 | user.CreatedAt = time.Now() 48 | user.Password = string(password) 49 | user.Token = uuid.NewV4().String() 50 | 51 | err = user.validate() 52 | 53 | if err != nil { 54 | return err 55 | } 56 | 57 | return nil 58 | 59 | } 60 | 61 | func (user *User) IsCorrectPassword(password string) bool { 62 | err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password)) 63 | return err == nil 64 | } 65 | 66 | func (user *User) validate() error { 67 | 68 | _, err := govalidator.ValidateStruct(user) 69 | 70 | if err != nil { 71 | return err 72 | } 73 | 74 | return nil 75 | } 76 | -------------------------------------------------------------------------------- /domain/user_test.go: -------------------------------------------------------------------------------- 1 | package domain_test 2 | 3 | import ( 4 | "github.com/asaskevich/govalidator" 5 | "github.com/codeedu/codeedu-plataforma-desafios/domain" 6 | "github.com/stretchr/testify/require" 7 | "testing" 8 | ) 9 | 10 | func TestNewUser(t *testing.T) { 11 | t.Parallel() 12 | 13 | _, err := domain.NewUser("Wesley", "wesleyxwesleyxxxgmail.com", "12345678") 14 | require.Error(t, err) 15 | 16 | _, err = domain.NewUser("Wesley", "wesleyxwesleyxxxgmail.com", "") 17 | require.Error(t, err) 18 | 19 | _, err = domain.NewUser("", "wesleyxwesleyxxxgmail.com", "") 20 | require.Error(t, err) 21 | 22 | user, err := domain.NewUser("Wesley", "wesleyxwesleyxxx@gmail.com", "12345678") 23 | require.Nil(t, err) 24 | 25 | govalidator.IsUUIDv4(user.Token) 26 | 27 | } 28 | -------------------------------------------------------------------------------- /framework/cmd/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "github.com/codeedu/codeedu-plataforma-desafios/application/repositories" 7 | "github.com/codeedu/codeedu-plataforma-desafios/application/usecases" 8 | "github.com/codeedu/codeedu-plataforma-desafios/framework/pb" 9 | "github.com/codeedu/codeedu-plataforma-desafios/framework/servers" 10 | "github.com/codeedu/codeedu-plataforma-desafios/framework/utils" 11 | "github.com/jinzhu/gorm" 12 | "github.com/joho/godotenv" 13 | _ "github.com/lib/pq" 14 | "google.golang.org/grpc" 15 | "google.golang.org/grpc/reflection" 16 | "log" 17 | "net" 18 | "os" 19 | ) 20 | 21 | var db *gorm.DB 22 | 23 | func init() { 24 | err := godotenv.Load() 25 | 26 | if err != nil { 27 | log.Fatalf("Error loading .env file") 28 | } 29 | } 30 | 31 | func main() { 32 | 33 | db = utils.ConnectDB(os.Getenv("env")) 34 | 35 | port := flag.Int("port", 0, "the server port") 36 | flag.Parse() 37 | log.Printf("start server on port %d", *port) 38 | 39 | userServer := setUpUserServer() 40 | challengeServer := setUpChallengeServer() 41 | 42 | grpcServer := grpc.NewServer() 43 | pb.RegisterUserServiceServer(grpcServer, userServer) 44 | pb.RegisterChallengeServiceServer(grpcServer, challengeServer) 45 | reflection.Register(grpcServer) 46 | 47 | address := fmt.Sprintf("0.0.0.0:%d", *port) 48 | listener, err := net.Listen("tcp", address) 49 | if err != nil { 50 | log.Fatal("cannot start server: ", err) 51 | } 52 | 53 | err = grpcServer.Serve(listener) 54 | if err != nil { 55 | log.Fatal("cannot start server: ", err) 56 | } 57 | } 58 | 59 | func setUpUserServer() *servers.UserServer { 60 | userServer := servers.NewUserServer() 61 | userRepository := repositories.UserRepositoryDb{Db: db} 62 | userServer.UserUseCase = usecases.UserUseCase{UserRepository: userRepository} 63 | return userServer 64 | } 65 | 66 | func setUpChallengeServer() *servers.ChallengeServer { 67 | challengeServer := servers.NewChallengeServer() 68 | challengeRepository := repositories.ChallengeRepositoryDb{Db: db} 69 | challengeServer.ChallengeUseCase = usecases.ChallengeUseCase{ChallengeRepository: challengeRepository} 70 | return challengeServer 71 | } 72 | -------------------------------------------------------------------------------- /framework/pb/challenge_message.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: challenge_message.proto 3 | 4 | package pb 5 | 6 | import ( 7 | context "context" 8 | fmt "fmt" 9 | proto "github.com/golang/protobuf/proto" 10 | grpc "google.golang.org/grpc" 11 | codes "google.golang.org/grpc/codes" 12 | status "google.golang.org/grpc/status" 13 | math "math" 14 | ) 15 | 16 | // Reference imports to suppress errors if they are not otherwise used. 17 | var _ = proto.Marshal 18 | var _ = fmt.Errorf 19 | var _ = math.Inf 20 | 21 | // This is a compile-time assertion to ensure that this generated file 22 | // is compatible with the proto package it is being compiled against. 23 | // A compilation error at this line likely means your copy of the 24 | // proto package needs to be updated. 25 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 26 | 27 | type Challenge struct { 28 | Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` 29 | Slug string `protobuf:"bytes,2,opt,name=slug,proto3" json:"slug,omitempty"` 30 | Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` 31 | Tags string `protobuf:"bytes,4,opt,name=tags,proto3" json:"tags,omitempty"` 32 | Requirements string `protobuf:"bytes,5,opt,name=requirements,proto3" json:"requirements,omitempty"` 33 | File []*ChallengeFile `protobuf:"bytes,6,rep,name=file,proto3" json:"file,omitempty"` 34 | Level string `protobuf:"bytes,7,opt,name=level,proto3" json:"level,omitempty"` 35 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 36 | XXX_unrecognized []byte `json:"-"` 37 | XXX_sizecache int32 `json:"-"` 38 | } 39 | 40 | func (m *Challenge) Reset() { *m = Challenge{} } 41 | func (m *Challenge) String() string { return proto.CompactTextString(m) } 42 | func (*Challenge) ProtoMessage() {} 43 | func (*Challenge) Descriptor() ([]byte, []int) { 44 | return fileDescriptor_9e18aabac6b3a996, []int{0} 45 | } 46 | 47 | func (m *Challenge) XXX_Unmarshal(b []byte) error { 48 | return xxx_messageInfo_Challenge.Unmarshal(m, b) 49 | } 50 | func (m *Challenge) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 51 | return xxx_messageInfo_Challenge.Marshal(b, m, deterministic) 52 | } 53 | func (m *Challenge) XXX_Merge(src proto.Message) { 54 | xxx_messageInfo_Challenge.Merge(m, src) 55 | } 56 | func (m *Challenge) XXX_Size() int { 57 | return xxx_messageInfo_Challenge.Size(m) 58 | } 59 | func (m *Challenge) XXX_DiscardUnknown() { 60 | xxx_messageInfo_Challenge.DiscardUnknown(m) 61 | } 62 | 63 | var xxx_messageInfo_Challenge proto.InternalMessageInfo 64 | 65 | func (m *Challenge) GetTitle() string { 66 | if m != nil { 67 | return m.Title 68 | } 69 | return "" 70 | } 71 | 72 | func (m *Challenge) GetSlug() string { 73 | if m != nil { 74 | return m.Slug 75 | } 76 | return "" 77 | } 78 | 79 | func (m *Challenge) GetDescription() string { 80 | if m != nil { 81 | return m.Description 82 | } 83 | return "" 84 | } 85 | 86 | func (m *Challenge) GetTags() string { 87 | if m != nil { 88 | return m.Tags 89 | } 90 | return "" 91 | } 92 | 93 | func (m *Challenge) GetRequirements() string { 94 | if m != nil { 95 | return m.Requirements 96 | } 97 | return "" 98 | } 99 | 100 | func (m *Challenge) GetFile() []*ChallengeFile { 101 | if m != nil { 102 | return m.File 103 | } 104 | return nil 105 | } 106 | 107 | func (m *Challenge) GetLevel() string { 108 | if m != nil { 109 | return m.Level 110 | } 111 | return "" 112 | } 113 | 114 | type ChallengeFile struct { 115 | Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` 116 | Url string `protobuf:"bytes,3,opt,name=url,proto3" json:"url,omitempty"` 117 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 118 | XXX_unrecognized []byte `json:"-"` 119 | XXX_sizecache int32 `json:"-"` 120 | } 121 | 122 | func (m *ChallengeFile) Reset() { *m = ChallengeFile{} } 123 | func (m *ChallengeFile) String() string { return proto.CompactTextString(m) } 124 | func (*ChallengeFile) ProtoMessage() {} 125 | func (*ChallengeFile) Descriptor() ([]byte, []int) { 126 | return fileDescriptor_9e18aabac6b3a996, []int{1} 127 | } 128 | 129 | func (m *ChallengeFile) XXX_Unmarshal(b []byte) error { 130 | return xxx_messageInfo_ChallengeFile.Unmarshal(m, b) 131 | } 132 | func (m *ChallengeFile) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 133 | return xxx_messageInfo_ChallengeFile.Marshal(b, m, deterministic) 134 | } 135 | func (m *ChallengeFile) XXX_Merge(src proto.Message) { 136 | xxx_messageInfo_ChallengeFile.Merge(m, src) 137 | } 138 | func (m *ChallengeFile) XXX_Size() int { 139 | return xxx_messageInfo_ChallengeFile.Size(m) 140 | } 141 | func (m *ChallengeFile) XXX_DiscardUnknown() { 142 | xxx_messageInfo_ChallengeFile.DiscardUnknown(m) 143 | } 144 | 145 | var xxx_messageInfo_ChallengeFile proto.InternalMessageInfo 146 | 147 | func (m *ChallengeFile) GetName() string { 148 | if m != nil { 149 | return m.Name 150 | } 151 | return "" 152 | } 153 | 154 | func (m *ChallengeFile) GetUrl() string { 155 | if m != nil { 156 | return m.Url 157 | } 158 | return "" 159 | } 160 | 161 | type NewChallengeRequest struct { 162 | Challenge *Challenge `protobuf:"bytes,1,opt,name=challenge,proto3" json:"challenge,omitempty"` 163 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 164 | XXX_unrecognized []byte `json:"-"` 165 | XXX_sizecache int32 `json:"-"` 166 | } 167 | 168 | func (m *NewChallengeRequest) Reset() { *m = NewChallengeRequest{} } 169 | func (m *NewChallengeRequest) String() string { return proto.CompactTextString(m) } 170 | func (*NewChallengeRequest) ProtoMessage() {} 171 | func (*NewChallengeRequest) Descriptor() ([]byte, []int) { 172 | return fileDescriptor_9e18aabac6b3a996, []int{2} 173 | } 174 | 175 | func (m *NewChallengeRequest) XXX_Unmarshal(b []byte) error { 176 | return xxx_messageInfo_NewChallengeRequest.Unmarshal(m, b) 177 | } 178 | func (m *NewChallengeRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 179 | return xxx_messageInfo_NewChallengeRequest.Marshal(b, m, deterministic) 180 | } 181 | func (m *NewChallengeRequest) XXX_Merge(src proto.Message) { 182 | xxx_messageInfo_NewChallengeRequest.Merge(m, src) 183 | } 184 | func (m *NewChallengeRequest) XXX_Size() int { 185 | return xxx_messageInfo_NewChallengeRequest.Size(m) 186 | } 187 | func (m *NewChallengeRequest) XXX_DiscardUnknown() { 188 | xxx_messageInfo_NewChallengeRequest.DiscardUnknown(m) 189 | } 190 | 191 | var xxx_messageInfo_NewChallengeRequest proto.InternalMessageInfo 192 | 193 | func (m *NewChallengeRequest) GetChallenge() *Challenge { 194 | if m != nil { 195 | return m.Challenge 196 | } 197 | return nil 198 | } 199 | 200 | type NewChallengeResponse struct { 201 | ChallengeId string `protobuf:"bytes,1,opt,name=challenge_id,json=challengeId,proto3" json:"challenge_id,omitempty"` 202 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 203 | XXX_unrecognized []byte `json:"-"` 204 | XXX_sizecache int32 `json:"-"` 205 | } 206 | 207 | func (m *NewChallengeResponse) Reset() { *m = NewChallengeResponse{} } 208 | func (m *NewChallengeResponse) String() string { return proto.CompactTextString(m) } 209 | func (*NewChallengeResponse) ProtoMessage() {} 210 | func (*NewChallengeResponse) Descriptor() ([]byte, []int) { 211 | return fileDescriptor_9e18aabac6b3a996, []int{3} 212 | } 213 | 214 | func (m *NewChallengeResponse) XXX_Unmarshal(b []byte) error { 215 | return xxx_messageInfo_NewChallengeResponse.Unmarshal(m, b) 216 | } 217 | func (m *NewChallengeResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 218 | return xxx_messageInfo_NewChallengeResponse.Marshal(b, m, deterministic) 219 | } 220 | func (m *NewChallengeResponse) XXX_Merge(src proto.Message) { 221 | xxx_messageInfo_NewChallengeResponse.Merge(m, src) 222 | } 223 | func (m *NewChallengeResponse) XXX_Size() int { 224 | return xxx_messageInfo_NewChallengeResponse.Size(m) 225 | } 226 | func (m *NewChallengeResponse) XXX_DiscardUnknown() { 227 | xxx_messageInfo_NewChallengeResponse.DiscardUnknown(m) 228 | } 229 | 230 | var xxx_messageInfo_NewChallengeResponse proto.InternalMessageInfo 231 | 232 | func (m *NewChallengeResponse) GetChallengeId() string { 233 | if m != nil { 234 | return m.ChallengeId 235 | } 236 | return "" 237 | } 238 | 239 | func init() { 240 | proto.RegisterType((*Challenge)(nil), "education.code.codeedu.Challenge") 241 | proto.RegisterType((*ChallengeFile)(nil), "education.code.codeedu.ChallengeFile") 242 | proto.RegisterType((*NewChallengeRequest)(nil), "education.code.codeedu.NewChallengeRequest") 243 | proto.RegisterType((*NewChallengeResponse)(nil), "education.code.codeedu.NewChallengeResponse") 244 | } 245 | 246 | func init() { 247 | proto.RegisterFile("challenge_message.proto", fileDescriptor_9e18aabac6b3a996) 248 | } 249 | 250 | var fileDescriptor_9e18aabac6b3a996 = []byte{ 251 | // 330 bytes of a gzipped FileDescriptorProto 252 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x92, 0x4f, 0x4b, 0xc3, 0x40, 253 | 0x10, 0xc5, 0x4d, 0x9b, 0x56, 0x3a, 0xa9, 0x58, 0xd6, 0xa2, 0x8b, 0xa7, 0x36, 0x20, 0x14, 0x94, 254 | 0x1c, 0x2a, 0x1e, 0x7a, 0x12, 0x2c, 0x08, 0x5e, 0x3c, 0x44, 0xf0, 0xe0, 0x45, 0xd2, 0x64, 0x8c, 255 | 0x0b, 0xdb, 0x4d, 0xba, 0x7f, 0xea, 0xdd, 0x4f, 0xea, 0x47, 0x91, 0xdd, 0xb4, 0xa9, 0x81, 0x8a, 256 | 0x5e, 0xc2, 0xdb, 0xb7, 0xfb, 0x86, 0xdf, 0xcc, 0x04, 0xce, 0xd2, 0xf7, 0x84, 0x73, 0x14, 0x39, 257 | 0xbe, 0x2e, 0x51, 0xa9, 0x24, 0xc7, 0xa8, 0x94, 0x85, 0x2e, 0xc8, 0x29, 0x66, 0x26, 0x4d, 0x34, 258 | 0x2b, 0x44, 0x94, 0x16, 0x19, 0xba, 0x0f, 0x66, 0x26, 0xfc, 0xf2, 0xa0, 0x37, 0xdf, 0x66, 0xc8, 259 | 0x10, 0x3a, 0x9a, 0x69, 0x8e, 0xd4, 0x1b, 0x79, 0x93, 0x5e, 0x5c, 0x1d, 0x08, 0x01, 0x5f, 0x71, 260 | 0x93, 0xd3, 0x96, 0x33, 0x9d, 0x26, 0x23, 0x08, 0x32, 0x54, 0xa9, 0x64, 0xa5, 0xad, 0x49, 0xdb, 261 | 0xee, 0xea, 0xa7, 0x65, 0x53, 0x3a, 0xc9, 0x15, 0xf5, 0xab, 0x94, 0xd5, 0x24, 0x84, 0xbe, 0xc4, 262 | 0x95, 0x61, 0x12, 0x97, 0x28, 0xb4, 0xa2, 0x1d, 0x77, 0xd7, 0xf0, 0xc8, 0x0c, 0xfc, 0x37, 0xc6, 263 | 0x91, 0x76, 0x47, 0xed, 0x49, 0x30, 0xbd, 0x88, 0xf6, 0x83, 0x47, 0x35, 0xf4, 0x3d, 0xe3, 0x18, 264 | 0xbb, 0x88, 0xc5, 0xe7, 0xb8, 0x46, 0x4e, 0x0f, 0x2b, 0x7c, 0x77, 0x08, 0x6f, 0xe0, 0xa8, 0xf1, 265 | 0xd8, 0x92, 0x89, 0x64, 0x89, 0xdb, 0x7e, 0xac, 0x26, 0x03, 0x68, 0x1b, 0xc9, 0x37, 0x7d, 0x58, 266 | 0x19, 0x3e, 0xc3, 0xc9, 0x23, 0x7e, 0xd4, 0xc9, 0x18, 0x57, 0x06, 0x95, 0x26, 0xb7, 0xd0, 0xab, 267 | 0x67, 0xec, 0xc6, 0x14, 0x4c, 0xc7, 0x7f, 0x32, 0xc6, 0xbb, 0x4c, 0x38, 0x83, 0x61, 0xb3, 0xae, 268 | 0x2a, 0x0b, 0xa1, 0x90, 0x8c, 0xa1, 0xbf, 0x5b, 0x1e, 0xcb, 0x36, 0x2b, 0x08, 0x6a, 0xef, 0x21, 269 | 0x9b, 0x7e, 0x7a, 0x30, 0xa8, 0x83, 0x4f, 0x28, 0xd7, 0x2c, 0x45, 0x22, 0xe0, 0x78, 0x2e, 0x31, 270 | 0xd1, 0xb8, 0x5b, 0xe3, 0xe5, 0x6f, 0x40, 0x7b, 0x1a, 0x3a, 0xbf, 0xfa, 0xdf, 0xe3, 0x8a, 0x32, 271 | 0x3c, 0xb8, 0xf3, 0x5f, 0x5a, 0xe5, 0x62, 0xd1, 0x75, 0xbf, 0xd5, 0xf5, 0x77, 0x00, 0x00, 0x00, 272 | 0xff, 0xff, 0x4c, 0x9a, 0x04, 0xac, 0x71, 0x02, 0x00, 0x00, 273 | } 274 | 275 | // Reference imports to suppress errors if they are not otherwise used. 276 | var _ context.Context 277 | var _ grpc.ClientConnInterface 278 | 279 | // This is a compile-time assertion to ensure that this generated file 280 | // is compatible with the grpc package it is being compiled against. 281 | const _ = grpc.SupportPackageIsVersion6 282 | 283 | // ChallengeServiceClient is the client API for ChallengeService service. 284 | // 285 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 286 | type ChallengeServiceClient interface { 287 | CreateChallenge(ctx context.Context, in *NewChallengeRequest, opts ...grpc.CallOption) (*NewChallengeResponse, error) 288 | } 289 | 290 | type challengeServiceClient struct { 291 | cc grpc.ClientConnInterface 292 | } 293 | 294 | func NewChallengeServiceClient(cc grpc.ClientConnInterface) ChallengeServiceClient { 295 | return &challengeServiceClient{cc} 296 | } 297 | 298 | func (c *challengeServiceClient) CreateChallenge(ctx context.Context, in *NewChallengeRequest, opts ...grpc.CallOption) (*NewChallengeResponse, error) { 299 | out := new(NewChallengeResponse) 300 | err := c.cc.Invoke(ctx, "/education.code.codeedu.ChallengeService/CreateChallenge", in, out, opts...) 301 | if err != nil { 302 | return nil, err 303 | } 304 | return out, nil 305 | } 306 | 307 | // ChallengeServiceServer is the server API for ChallengeService service. 308 | type ChallengeServiceServer interface { 309 | CreateChallenge(context.Context, *NewChallengeRequest) (*NewChallengeResponse, error) 310 | } 311 | 312 | // UnimplementedChallengeServiceServer can be embedded to have forward compatible implementations. 313 | type UnimplementedChallengeServiceServer struct { 314 | } 315 | 316 | func (*UnimplementedChallengeServiceServer) CreateChallenge(ctx context.Context, req *NewChallengeRequest) (*NewChallengeResponse, error) { 317 | return nil, status.Errorf(codes.Unimplemented, "method CreateChallenge not implemented") 318 | } 319 | 320 | func RegisterChallengeServiceServer(s *grpc.Server, srv ChallengeServiceServer) { 321 | s.RegisterService(&_ChallengeService_serviceDesc, srv) 322 | } 323 | 324 | func _ChallengeService_CreateChallenge_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 325 | in := new(NewChallengeRequest) 326 | if err := dec(in); err != nil { 327 | return nil, err 328 | } 329 | if interceptor == nil { 330 | return srv.(ChallengeServiceServer).CreateChallenge(ctx, in) 331 | } 332 | info := &grpc.UnaryServerInfo{ 333 | Server: srv, 334 | FullMethod: "/education.code.codeedu.ChallengeService/CreateChallenge", 335 | } 336 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 337 | return srv.(ChallengeServiceServer).CreateChallenge(ctx, req.(*NewChallengeRequest)) 338 | } 339 | return interceptor(ctx, in, info, handler) 340 | } 341 | 342 | var _ChallengeService_serviceDesc = grpc.ServiceDesc{ 343 | ServiceName: "education.code.codeedu.ChallengeService", 344 | HandlerType: (*ChallengeServiceServer)(nil), 345 | Methods: []grpc.MethodDesc{ 346 | { 347 | MethodName: "CreateChallenge", 348 | Handler: _ChallengeService_CreateChallenge_Handler, 349 | }, 350 | }, 351 | Streams: []grpc.StreamDesc{}, 352 | Metadata: "challenge_message.proto", 353 | } 354 | -------------------------------------------------------------------------------- /framework/pb/user_message.pb.go: -------------------------------------------------------------------------------- 1 | // Code generated by protoc-gen-go. DO NOT EDIT. 2 | // source: user_message.proto 3 | 4 | package pb 5 | 6 | import ( 7 | context "context" 8 | fmt "fmt" 9 | proto "github.com/golang/protobuf/proto" 10 | grpc "google.golang.org/grpc" 11 | codes "google.golang.org/grpc/codes" 12 | status "google.golang.org/grpc/status" 13 | math "math" 14 | ) 15 | 16 | // Reference imports to suppress errors if they are not otherwise used. 17 | var _ = proto.Marshal 18 | var _ = fmt.Errorf 19 | var _ = math.Inf 20 | 21 | // This is a compile-time assertion to ensure that this generated file 22 | // is compatible with the proto package it is being compiled against. 23 | // A compilation error at this line likely means your copy of the 24 | // proto package needs to be updated. 25 | const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package 26 | 27 | type UserRequest struct { 28 | Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` 29 | Email string `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"` 30 | Password string `protobuf:"bytes,3,opt,name=password,proto3" json:"password,omitempty"` 31 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 32 | XXX_unrecognized []byte `json:"-"` 33 | XXX_sizecache int32 `json:"-"` 34 | } 35 | 36 | func (m *UserRequest) Reset() { *m = UserRequest{} } 37 | func (m *UserRequest) String() string { return proto.CompactTextString(m) } 38 | func (*UserRequest) ProtoMessage() {} 39 | func (*UserRequest) Descriptor() ([]byte, []int) { 40 | return fileDescriptor_7965fb6944d08275, []int{0} 41 | } 42 | 43 | func (m *UserRequest) XXX_Unmarshal(b []byte) error { 44 | return xxx_messageInfo_UserRequest.Unmarshal(m, b) 45 | } 46 | func (m *UserRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 47 | return xxx_messageInfo_UserRequest.Marshal(b, m, deterministic) 48 | } 49 | func (m *UserRequest) XXX_Merge(src proto.Message) { 50 | xxx_messageInfo_UserRequest.Merge(m, src) 51 | } 52 | func (m *UserRequest) XXX_Size() int { 53 | return xxx_messageInfo_UserRequest.Size(m) 54 | } 55 | func (m *UserRequest) XXX_DiscardUnknown() { 56 | xxx_messageInfo_UserRequest.DiscardUnknown(m) 57 | } 58 | 59 | var xxx_messageInfo_UserRequest proto.InternalMessageInfo 60 | 61 | func (m *UserRequest) GetName() string { 62 | if m != nil { 63 | return m.Name 64 | } 65 | return "" 66 | } 67 | 68 | func (m *UserRequest) GetEmail() string { 69 | if m != nil { 70 | return m.Email 71 | } 72 | return "" 73 | } 74 | 75 | func (m *UserRequest) GetPassword() string { 76 | if m != nil { 77 | return m.Password 78 | } 79 | return "" 80 | } 81 | 82 | type UserResponse struct { 83 | Token string `protobuf:"bytes,1,opt,name=token,proto3" json:"token,omitempty"` 84 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 85 | XXX_unrecognized []byte `json:"-"` 86 | XXX_sizecache int32 `json:"-"` 87 | } 88 | 89 | func (m *UserResponse) Reset() { *m = UserResponse{} } 90 | func (m *UserResponse) String() string { return proto.CompactTextString(m) } 91 | func (*UserResponse) ProtoMessage() {} 92 | func (*UserResponse) Descriptor() ([]byte, []int) { 93 | return fileDescriptor_7965fb6944d08275, []int{1} 94 | } 95 | 96 | func (m *UserResponse) XXX_Unmarshal(b []byte) error { 97 | return xxx_messageInfo_UserResponse.Unmarshal(m, b) 98 | } 99 | func (m *UserResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 100 | return xxx_messageInfo_UserResponse.Marshal(b, m, deterministic) 101 | } 102 | func (m *UserResponse) XXX_Merge(src proto.Message) { 103 | xxx_messageInfo_UserResponse.Merge(m, src) 104 | } 105 | func (m *UserResponse) XXX_Size() int { 106 | return xxx_messageInfo_UserResponse.Size(m) 107 | } 108 | func (m *UserResponse) XXX_DiscardUnknown() { 109 | xxx_messageInfo_UserResponse.DiscardUnknown(m) 110 | } 111 | 112 | var xxx_messageInfo_UserResponse proto.InternalMessageInfo 113 | 114 | func (m *UserResponse) GetToken() string { 115 | if m != nil { 116 | return m.Token 117 | } 118 | return "" 119 | } 120 | 121 | type UserAuthRequest struct { 122 | Email string `protobuf:"bytes,1,opt,name=email,proto3" json:"email,omitempty"` 123 | Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"` 124 | XXX_NoUnkeyedLiteral struct{} `json:"-"` 125 | XXX_unrecognized []byte `json:"-"` 126 | XXX_sizecache int32 `json:"-"` 127 | } 128 | 129 | func (m *UserAuthRequest) Reset() { *m = UserAuthRequest{} } 130 | func (m *UserAuthRequest) String() string { return proto.CompactTextString(m) } 131 | func (*UserAuthRequest) ProtoMessage() {} 132 | func (*UserAuthRequest) Descriptor() ([]byte, []int) { 133 | return fileDescriptor_7965fb6944d08275, []int{2} 134 | } 135 | 136 | func (m *UserAuthRequest) XXX_Unmarshal(b []byte) error { 137 | return xxx_messageInfo_UserAuthRequest.Unmarshal(m, b) 138 | } 139 | func (m *UserAuthRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { 140 | return xxx_messageInfo_UserAuthRequest.Marshal(b, m, deterministic) 141 | } 142 | func (m *UserAuthRequest) XXX_Merge(src proto.Message) { 143 | xxx_messageInfo_UserAuthRequest.Merge(m, src) 144 | } 145 | func (m *UserAuthRequest) XXX_Size() int { 146 | return xxx_messageInfo_UserAuthRequest.Size(m) 147 | } 148 | func (m *UserAuthRequest) XXX_DiscardUnknown() { 149 | xxx_messageInfo_UserAuthRequest.DiscardUnknown(m) 150 | } 151 | 152 | var xxx_messageInfo_UserAuthRequest proto.InternalMessageInfo 153 | 154 | func (m *UserAuthRequest) GetEmail() string { 155 | if m != nil { 156 | return m.Email 157 | } 158 | return "" 159 | } 160 | 161 | func (m *UserAuthRequest) GetPassword() string { 162 | if m != nil { 163 | return m.Password 164 | } 165 | return "" 166 | } 167 | 168 | func init() { 169 | proto.RegisterType((*UserRequest)(nil), "education.code.codeedu.UserRequest") 170 | proto.RegisterType((*UserResponse)(nil), "education.code.codeedu.UserResponse") 171 | proto.RegisterType((*UserAuthRequest)(nil), "education.code.codeedu.UserAuthRequest") 172 | } 173 | 174 | func init() { 175 | proto.RegisterFile("user_message.proto", fileDescriptor_7965fb6944d08275) 176 | } 177 | 178 | var fileDescriptor_7965fb6944d08275 = []byte{ 179 | // 238 bytes of a gzipped FileDescriptorProto 180 | 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x91, 0x41, 0x4b, 0xc4, 0x30, 181 | 0x10, 0x85, 0x6d, 0xad, 0xa2, 0xa3, 0x20, 0x0c, 0x22, 0x65, 0x4f, 0x52, 0x17, 0xf4, 0xd4, 0x83, 182 | 0xfe, 0x02, 0xdd, 0x7f, 0xb0, 0x8b, 0x88, 0x5e, 0x24, 0xdb, 0x3e, 0xb4, 0x68, 0x93, 0x98, 0x49, 183 | 0xf4, 0xf7, 0xf9, 0xcf, 0xa4, 0x89, 0x2e, 0x2b, 0x68, 0xd9, 0x4b, 0xc8, 0x9b, 0x3c, 0xde, 0xcb, 184 | 0xc7, 0x10, 0x07, 0x81, 0x7b, 0xec, 0x21, 0xa2, 0x9e, 0x50, 0x5b, 0x67, 0xbc, 0xe1, 0x13, 0xb4, 185 | 0xa1, 0x51, 0xbe, 0x33, 0xba, 0x6e, 0x4c, 0x8b, 0x78, 0xa0, 0x0d, 0xd5, 0x82, 0x0e, 0x6e, 0x05, 186 | 0x6e, 0x8e, 0xb7, 0x00, 0xf1, 0xcc, 0x54, 0x68, 0xd5, 0xa3, 0xcc, 0x4e, 0xb3, 0x8b, 0xfd, 0x79, 187 | 0xbc, 0xf3, 0x31, 0xed, 0xa0, 0x57, 0xdd, 0x6b, 0x99, 0xc7, 0x61, 0x12, 0x3c, 0xa1, 0x3d, 0xab, 188 | 0x44, 0x3e, 0x8c, 0x6b, 0xcb, 0xed, 0xf8, 0xb0, 0xd2, 0xd5, 0x94, 0x0e, 0x53, 0xa8, 0x58, 0xa3, 189 | 0x25, 0x26, 0x78, 0xf3, 0x02, 0xfd, 0x1d, 0x9b, 0x44, 0x35, 0xa3, 0xa3, 0xc1, 0x75, 0x1d, 0xfc, 190 | 0xf3, 0x4f, 0xfd, 0xaa, 0x2a, 0xfb, 0xaf, 0x2a, 0xff, 0x5d, 0x75, 0xf9, 0x99, 0x25, 0x80, 0x05, 191 | 0xdc, 0x7b, 0xd7, 0x80, 0xef, 0x89, 0x66, 0x0e, 0xca, 0x63, 0x18, 0xf2, 0x59, 0xfd, 0x37, 0x76, 192 | 0xbd, 0xc6, 0x3c, 0x99, 0x8e, 0x9b, 0x12, 0x43, 0xb5, 0xc5, 0x77, 0x54, 0x0c, 0x7f, 0xe5, 0xf3, 193 | 0x31, 0xff, 0x1a, 0xcd, 0xa6, 0xc1, 0x37, 0xc5, 0x43, 0x6e, 0x97, 0xcb, 0xdd, 0xb8, 0xa8, 0xab, 194 | 0xaf, 0x00, 0x00, 0x00, 0xff, 0xff, 0xd7, 0xeb, 0xf2, 0x9d, 0xbe, 0x01, 0x00, 0x00, 195 | } 196 | 197 | // Reference imports to suppress errors if they are not otherwise used. 198 | var _ context.Context 199 | var _ grpc.ClientConnInterface 200 | 201 | // This is a compile-time assertion to ensure that this generated file 202 | // is compatible with the grpc package it is being compiled against. 203 | const _ = grpc.SupportPackageIsVersion6 204 | 205 | // UserServiceClient is the client API for UserService service. 206 | // 207 | // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. 208 | type UserServiceClient interface { 209 | CreateUser(ctx context.Context, in *UserRequest, opts ...grpc.CallOption) (*UserResponse, error) 210 | Auth(ctx context.Context, in *UserAuthRequest, opts ...grpc.CallOption) (*UserResponse, error) 211 | } 212 | 213 | type userServiceClient struct { 214 | cc grpc.ClientConnInterface 215 | } 216 | 217 | func NewUserServiceClient(cc grpc.ClientConnInterface) UserServiceClient { 218 | return &userServiceClient{cc} 219 | } 220 | 221 | func (c *userServiceClient) CreateUser(ctx context.Context, in *UserRequest, opts ...grpc.CallOption) (*UserResponse, error) { 222 | out := new(UserResponse) 223 | err := c.cc.Invoke(ctx, "/education.code.codeedu.UserService/CreateUser", in, out, opts...) 224 | if err != nil { 225 | return nil, err 226 | } 227 | return out, nil 228 | } 229 | 230 | func (c *userServiceClient) Auth(ctx context.Context, in *UserAuthRequest, opts ...grpc.CallOption) (*UserResponse, error) { 231 | out := new(UserResponse) 232 | err := c.cc.Invoke(ctx, "/education.code.codeedu.UserService/Auth", in, out, opts...) 233 | if err != nil { 234 | return nil, err 235 | } 236 | return out, nil 237 | } 238 | 239 | // UserServiceServer is the server API for UserService service. 240 | type UserServiceServer interface { 241 | CreateUser(context.Context, *UserRequest) (*UserResponse, error) 242 | Auth(context.Context, *UserAuthRequest) (*UserResponse, error) 243 | } 244 | 245 | // UnimplementedUserServiceServer can be embedded to have forward compatible implementations. 246 | type UnimplementedUserServiceServer struct { 247 | } 248 | 249 | func (*UnimplementedUserServiceServer) CreateUser(ctx context.Context, req *UserRequest) (*UserResponse, error) { 250 | return nil, status.Errorf(codes.Unimplemented, "method CreateUser not implemented") 251 | } 252 | func (*UnimplementedUserServiceServer) Auth(ctx context.Context, req *UserAuthRequest) (*UserResponse, error) { 253 | return nil, status.Errorf(codes.Unimplemented, "method Auth not implemented") 254 | } 255 | 256 | func RegisterUserServiceServer(s *grpc.Server, srv UserServiceServer) { 257 | s.RegisterService(&_UserService_serviceDesc, srv) 258 | } 259 | 260 | func _UserService_CreateUser_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 261 | in := new(UserRequest) 262 | if err := dec(in); err != nil { 263 | return nil, err 264 | } 265 | if interceptor == nil { 266 | return srv.(UserServiceServer).CreateUser(ctx, in) 267 | } 268 | info := &grpc.UnaryServerInfo{ 269 | Server: srv, 270 | FullMethod: "/education.code.codeedu.UserService/CreateUser", 271 | } 272 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 273 | return srv.(UserServiceServer).CreateUser(ctx, req.(*UserRequest)) 274 | } 275 | return interceptor(ctx, in, info, handler) 276 | } 277 | 278 | func _UserService_Auth_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { 279 | in := new(UserAuthRequest) 280 | if err := dec(in); err != nil { 281 | return nil, err 282 | } 283 | if interceptor == nil { 284 | return srv.(UserServiceServer).Auth(ctx, in) 285 | } 286 | info := &grpc.UnaryServerInfo{ 287 | Server: srv, 288 | FullMethod: "/education.code.codeedu.UserService/Auth", 289 | } 290 | handler := func(ctx context.Context, req interface{}) (interface{}, error) { 291 | return srv.(UserServiceServer).Auth(ctx, req.(*UserAuthRequest)) 292 | } 293 | return interceptor(ctx, in, info, handler) 294 | } 295 | 296 | var _UserService_serviceDesc = grpc.ServiceDesc{ 297 | ServiceName: "education.code.codeedu.UserService", 298 | HandlerType: (*UserServiceServer)(nil), 299 | Methods: []grpc.MethodDesc{ 300 | { 301 | MethodName: "CreateUser", 302 | Handler: _UserService_CreateUser_Handler, 303 | }, 304 | { 305 | MethodName: "Auth", 306 | Handler: _UserService_Auth_Handler, 307 | }, 308 | }, 309 | Streams: []grpc.StreamDesc{}, 310 | Metadata: "user_message.proto", 311 | } 312 | -------------------------------------------------------------------------------- /framework/servers/challenge_server.go: -------------------------------------------------------------------------------- 1 | package servers 2 | 3 | import ( 4 | "context" 5 | "github.com/codeedu/codeedu-plataforma-desafios/application/usecases" 6 | "github.com/codeedu/codeedu-plataforma-desafios/domain" 7 | "github.com/codeedu/codeedu-plataforma-desafios/framework/pb" 8 | "google.golang.org/grpc/codes" 9 | "google.golang.org/grpc/status" 10 | ) 11 | 12 | type ChallengeServer struct { 13 | ChallengeUseCase usecases.ChallengeUseCase 14 | } 15 | 16 | func NewChallengeServer() *ChallengeServer { 17 | return &ChallengeServer{} 18 | } 19 | 20 | func (ChallengeServer *ChallengeServer) CreateChallenge(ctx context.Context, req *pb.NewChallengeRequest) (*pb.NewChallengeResponse, error) { 21 | 22 | challenge := domain.NewChallenge() 23 | challenge.Title = req.GetChallenge().GetTitle() 24 | challenge.Slug = req.GetChallenge().GetSlug() 25 | challenge.Description = req.GetChallenge().GetDescription() 26 | challenge.Requirements = req.GetChallenge().GetRequirements() 27 | challenge.Tags = req.GetChallenge().GetTags() 28 | challenge.Level = req.GetChallenge().GetLevel() 29 | 30 | var files []*domain.ChallengeFile 31 | for _, f := range req.Challenge.GetFile() { 32 | file, err := domain.NewChallengeFile(f.Name, f.Url) 33 | 34 | if err != nil { 35 | return nil, status.Errorf(codes.InvalidArgument, "Error during the validation: %v", err) 36 | } 37 | file.ChallengeID = challenge.ID 38 | files = append(files, file) 39 | } 40 | 41 | challenge.ChallengeFiles = files 42 | 43 | if err := challenge.Valid(); err != nil { 44 | return nil, status.Errorf(codes.InvalidArgument, "Error during the validation: %v", err) 45 | } 46 | 47 | newChallenge, err := ChallengeServer.ChallengeUseCase.Create(challenge) 48 | 49 | if err != nil { 50 | return nil, status.Errorf(codes.Internal, "Error persisting information: %v", err) 51 | } 52 | 53 | return &pb.NewChallengeResponse{ 54 | ChallengeId: newChallenge.ID, 55 | }, nil 56 | } 57 | -------------------------------------------------------------------------------- /framework/servers/user_server.go: -------------------------------------------------------------------------------- 1 | package servers 2 | 3 | import ( 4 | "context" 5 | "github.com/codeedu/codeedu-plataforma-desafios/application/usecases" 6 | "github.com/codeedu/codeedu-plataforma-desafios/domain" 7 | "github.com/codeedu/codeedu-plataforma-desafios/framework/pb" 8 | "google.golang.org/grpc/codes" 9 | "google.golang.org/grpc/status" 10 | ) 11 | 12 | type UserServer struct { 13 | UserUseCase usecases.UserUseCase 14 | } 15 | 16 | func NewUserServer() *UserServer { 17 | return &UserServer{} 18 | } 19 | 20 | func (UserServer *UserServer) CreateUser(ctx context.Context, req *pb.UserRequest) (*pb.UserResponse, error) { 21 | 22 | user, err := domain.NewUser(req.GetName(), req.GetEmail(), req.GetPassword()) 23 | 24 | if err != nil { 25 | return nil, status.Errorf(codes.InvalidArgument, "Error during the validation: %v", err) 26 | } 27 | 28 | newUser, err := UserServer.UserUseCase.Create(user) 29 | 30 | if err != nil { 31 | return nil, status.Errorf(codes.Internal, "Error persisting information: %v", err) 32 | } 33 | 34 | return &pb.UserResponse{ 35 | Token: newUser.Token, 36 | }, nil 37 | } 38 | 39 | func (UserServer *UserServer) Auth(ctx context.Context, req *pb.UserAuthRequest) (*pb.UserResponse, error) { 40 | 41 | user, err := UserServer.UserUseCase.Auth(req.GetEmail(), req.GetPassword()) 42 | 43 | if err != nil { 44 | return nil, status.Errorf(codes.PermissionDenied, "Email and password don't match") 45 | } 46 | 47 | return &pb.UserResponse{ 48 | Token: user.Token, 49 | }, nil 50 | 51 | } 52 | -------------------------------------------------------------------------------- /framework/servers/user_server_test.go: -------------------------------------------------------------------------------- 1 | package servers_test 2 | 3 | import ( 4 | "github.com/jinzhu/gorm" 5 | _ "github.com/lib/pq" 6 | "testing" 7 | ) 8 | 9 | var db *gorm.DB 10 | 11 | func TestServerCreateUser(t *testing.T) { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /framework/utils/db.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "github.com/codeedu/codeedu-plataforma-desafios/domain" 5 | "github.com/jinzhu/gorm" 6 | _ "github.com/jinzhu/gorm/dialects/sqlite" 7 | "github.com/joho/godotenv" 8 | _ "github.com/lib/pq" 9 | "log" 10 | "os" 11 | "path/filepath" 12 | "runtime" 13 | ) 14 | 15 | func init() { 16 | _, b, _, _ := runtime.Caller(0) 17 | basepath := filepath.Dir(b) 18 | 19 | err := godotenv.Load(basepath + "/../../.env") 20 | 21 | if err != nil { 22 | log.Fatalf("Error loading .env files") 23 | } 24 | } 25 | 26 | func ConnectDB(env string) *gorm.DB { 27 | var dsn string 28 | var db *gorm.DB 29 | var err error 30 | 31 | if env != "test" { 32 | dsn = os.Getenv("dsn") 33 | db, err = gorm.Open(os.Getenv("dbType"), dsn) 34 | } else { 35 | dsn = os.Getenv("dsnTest") 36 | db, err = gorm.Open(os.Getenv("dbTypeTest"), dsn) 37 | } 38 | 39 | if err != nil { 40 | log.Fatalf("Error connecting to database: %v", err) 41 | panic(err) 42 | } 43 | 44 | if os.Getenv("debug") == "true" { 45 | db.LogMode(true) 46 | } 47 | 48 | if os.Getenv("AutoMigrateDb") == "true" { 49 | db.AutoMigrate(&domain.User{}, &domain.Author{}, &domain.Challenge{}, &domain.ChallengeFile{}) 50 | db.Model(domain.ChallengeFile{}).AddForeignKey("challenge_id", "challenges (id)", "CASCADE", "CASCADE") 51 | } 52 | 53 | //defer db.Close() 54 | 55 | return db 56 | } 57 | -------------------------------------------------------------------------------- /framework/utils/utils.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "github.com/jessevdk/go-flags" 5 | "os" 6 | ) 7 | 8 | type ConfigOptions struct { 9 | Token string `short:"t" long:"token" description:"Token" required:"true"` 10 | } 11 | 12 | func CheckConfigFlags(parser *flags.Parser) { 13 | if _, err := parser.Parse(); err != nil { 14 | if flagsErr, ok := err.(*flags.Error); ok && flagsErr.Type == flags.ErrHelp { 15 | os.Exit(0) 16 | } else { 17 | os.Exit(1) 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/codeedu/codeedu-plataforma-desafios 2 | 3 | go 1.14 4 | 5 | require ( 6 | github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 7 | github.com/bxcodec/faker/v3 v3.3.0 8 | github.com/golang/protobuf v1.3.5 9 | github.com/jessevdk/go-flags v1.4.0 10 | github.com/jinzhu/gorm v1.9.12 11 | github.com/joho/godotenv v1.3.0 12 | github.com/lib/pq v1.3.0 13 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect 14 | github.com/satori/go.uuid v1.2.0 15 | github.com/stretchr/testify v1.5.1 16 | golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd 17 | google.golang.org/appengine v1.4.0 18 | google.golang.org/grpc v1.28.1 19 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect 20 | ) 21 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 3 | github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 h1:zV3ejI06GQ59hwDQAvmK1qxOQGB3WuVTRoY0okPTAv0= 4 | github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= 5 | github.com/bxcodec/faker/v3 v3.3.0 h1:w/GnJDXnn8b49hLqU948jZj1pqcb8y7sTE822KzO+xc= 6 | github.com/bxcodec/faker/v3 v3.3.0/go.mod h1:gF31YgnMSMKgkvl+fyEo1xuSMbEuieyqfeslGYFjneM= 7 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 8 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 9 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 10 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 11 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 12 | github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd h1:83Wprp6ROGeiHFAP8WJdI2RoxALQYgdllERc3N5N2DM= 13 | github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= 14 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 15 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 16 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 17 | github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5 h1:Yzb9+7DPaBjB8zlTR87/ElzFsnQfuHnVUVqpZZIcV5Y= 18 | github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= 19 | github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= 20 | github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= 21 | github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= 22 | github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= 23 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 24 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 25 | github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= 26 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 27 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 28 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 29 | github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= 30 | github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= 31 | github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ= 32 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 33 | github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= 34 | github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 35 | github.com/jinzhu/gorm v1.9.12 h1:Drgk1clyWT9t9ERbzHza6Mj/8FY/CqMyVzOiHviMo6Q= 36 | github.com/jinzhu/gorm v1.9.12/go.mod h1:vhTjlKSJUTWNtcbQtrMBFCxy7eXTzeCAzfL5fBZT/Qs= 37 | github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= 38 | github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= 39 | github.com/jinzhu/now v1.0.1 h1:HjfetcXq097iXP0uoPCdnM4Efp5/9MsM0/M+XOTeR3M= 40 | github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 41 | github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= 42 | github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= 43 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 44 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 45 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 46 | github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= 47 | github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU= 48 | github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= 49 | github.com/mattn/go-sqlite3 v2.0.1+incompatible h1:xQ15muvnzGBHpIpdrNi1DA5x0+TcBZzsIDwmw9uTHzw= 50 | github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= 51 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= 52 | github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= 53 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 54 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 55 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 56 | github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww= 57 | github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= 58 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 59 | github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= 60 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 61 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 62 | golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 63 | golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd h1:GGJVjV8waZKRHrgwvtH66z9ZGVurTD1MT0n1Bb+q4aM= 64 | golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 65 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 66 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 67 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 68 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 69 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 70 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 71 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 72 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 73 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= 74 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 75 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 76 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 77 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 78 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 79 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 80 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 81 | golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= 82 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 83 | golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= 84 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 85 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 86 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 87 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 88 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 89 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 90 | google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= 91 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 92 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 93 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE= 94 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 95 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 96 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 97 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 98 | google.golang.org/grpc v1.28.1 h1:C1QC6KzgSiLyBabDi87BbjaGreoRgGUF5nOyvfrAZ1k= 99 | google.golang.org/grpc v1.28.1/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 100 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 101 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= 102 | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 103 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= 104 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 105 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 106 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 107 | -------------------------------------------------------------------------------- /proto/challenge_message.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package education.code.codeedu; 4 | 5 | option go_package = "pb"; 6 | 7 | message Challenge { 8 | string title = 1; 9 | string slug = 2; 10 | string description = 3; 11 | string tags = 4; 12 | string requirements = 5; 13 | repeated ChallengeFile file = 6; 14 | string level = 7; 15 | } 16 | 17 | message ChallengeFile { 18 | string name = 2; 19 | string url = 3; 20 | } 21 | 22 | message NewChallengeRequest { 23 | Challenge challenge = 1; 24 | } 25 | 26 | 27 | message NewChallengeResponse { 28 | string challenge_id = 1; 29 | } 30 | 31 | service ChallengeService { 32 | rpc CreateChallenge (NewChallengeRequest) returns (NewChallengeResponse) {}; 33 | } -------------------------------------------------------------------------------- /proto/user_message.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package education.code.codeedu; 4 | 5 | option go_package = "pb"; 6 | 7 | message UserRequest { 8 | string name = 1; 9 | string email = 2; 10 | string password = 3; 11 | } 12 | 13 | message UserResponse { 14 | string token = 1; 15 | } 16 | 17 | message UserAuthRequest { 18 | string email = 1; 19 | string password = 2; 20 | } 21 | 22 | service UserService { 23 | rpc CreateUser (UserRequest) returns (UserResponse) {}; 24 | rpc Auth(UserAuthRequest) returns (UserResponse) {}; 25 | } -------------------------------------------------------------------------------- /sonar-project.properties: -------------------------------------------------------------------------------- 1 | sonar.organization=codeedu 2 | sonar.projectKey=codeedu_codeedu-plataforma-desafios 3 | 4 | # relative paths to source directories. More details and properties are described 5 | # in https://sonarcloud.io/documentation/project-administration/narrowing-the-focus/ 6 | sonar.sources=. 7 | sonar.exclusions=framework/pb/* 8 | sonar.test.exclusions=framework/pb/* --------------------------------------------------------------------------------