-
Notifications
You must be signed in to change notification settings - Fork 2.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
91 changed files
with
13,103 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
out | ||
.env | ||
learn-cicd-starter |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
# learn-cicd-starter | ||
The starter code for the "Learn CICD" course on Boot.dev | ||
# learn-cicd-starter (Notely) | ||
|
||
The starter code for the "Notely" application for the "Learn CICD" course on [Boot.dev](https://boot.dev). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
module github.com/bootdotdev/learn-cicd-starter | ||
|
||
go 1.20 | ||
|
||
require ( | ||
github.com/go-chi/chi v1.5.4 | ||
github.com/go-chi/cors v1.2.1 | ||
github.com/google/uuid v1.3.0 | ||
github.com/joho/godotenv v1.5.1 | ||
) | ||
|
||
require github.com/go-sql-driver/mysql v1.7.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
github.com/go-chi/chi v1.5.4 h1:QHdzF2szwjqVV4wmByUnTcsbIg7UGaQ0tPF2t5GcAIs= | ||
github.com/go-chi/chi v1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIuEg= | ||
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4= | ||
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58= | ||
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= | ||
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= | ||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= | ||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= | ||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"net/http" | ||
"time" | ||
|
||
"github.com/bootdotdev/learn-cicd-starter/internal/database" | ||
"github.com/go-chi/chi" | ||
"github.com/google/uuid" | ||
) | ||
|
||
func (cfg *apiConfig) handlerNotesGet(w http.ResponseWriter, r *http.Request, user database.User) { | ||
posts, err := cfg.DB.GetNotesForUser(r.Context(), user.ID) | ||
if err != nil { | ||
respondWithError(w, http.StatusInternalServerError, "Couldn't get posts for user") | ||
return | ||
} | ||
|
||
respondWithJSON(w, http.StatusOK, databasePostsToPosts(posts)) | ||
} | ||
|
||
func (cfg *apiConfig) handlerNotesUpdate(w http.ResponseWriter, r *http.Request, user database.User) { | ||
type parameters struct { | ||
Note string `json:"note"` | ||
} | ||
decoder := json.NewDecoder(r.Body) | ||
params := parameters{} | ||
err := decoder.Decode(¶ms) | ||
if err != nil { | ||
respondWithError(w, http.StatusInternalServerError, "Couldn't decode parameters") | ||
return | ||
} | ||
|
||
noteID := chi.URLParam(r, "noteID") | ||
note, err := cfg.DB.GetNote(r.Context(), noteID) | ||
if err != nil { | ||
respondWithError(w, http.StatusNotFound, "Couldn't get note") | ||
return | ||
} | ||
if note.UserID != user.ID { | ||
respondWithError(w, http.StatusForbidden, "Can't update another user's note") | ||
return | ||
} | ||
|
||
err = cfg.DB.UpdateNote(r.Context(), database.UpdateNoteParams{ | ||
UpdatedAt: time.Now().UTC(), | ||
Note: params.Note, | ||
ID: noteID, | ||
}) | ||
if err != nil { | ||
respondWithError(w, http.StatusInternalServerError, "Couldn't update note") | ||
return | ||
} | ||
|
||
note, err = cfg.DB.GetNote(r.Context(), noteID) | ||
if err != nil { | ||
respondWithError(w, http.StatusNotFound, "Couldn't get note") | ||
return | ||
} | ||
respondWithJSON(w, http.StatusOK, databaseNoteToNote(note)) | ||
} | ||
|
||
func (cfg *apiConfig) handlerNotesDelete(w http.ResponseWriter, r *http.Request, user database.User) { | ||
noteID := chi.URLParam(r, "noteID") | ||
note, err := cfg.DB.GetNote(r.Context(), noteID) | ||
if err != nil { | ||
respondWithError(w, http.StatusNotFound, "Couldn't get note") | ||
return | ||
} | ||
if note.UserID != user.ID { | ||
respondWithError(w, http.StatusForbidden, "Can't update another user's note") | ||
return | ||
} | ||
|
||
err = cfg.DB.DeleteNote(r.Context(), noteID) | ||
if err != nil { | ||
respondWithError(w, http.StatusInternalServerError, "Couldn't delete note") | ||
return | ||
} | ||
respondWithJSON(w, http.StatusOK, struct{}{}) | ||
} | ||
|
||
func (cfg *apiConfig) handlerNotesCreate(w http.ResponseWriter, r *http.Request, user database.User) { | ||
type parameters struct { | ||
Note string `json:"note"` | ||
} | ||
decoder := json.NewDecoder(r.Body) | ||
params := parameters{} | ||
err := decoder.Decode(¶ms) | ||
if err != nil { | ||
respondWithError(w, http.StatusInternalServerError, "Couldn't decode parameters") | ||
return | ||
} | ||
|
||
id := uuid.New().String() | ||
err = cfg.DB.CreateNote(r.Context(), database.CreateNoteParams{ | ||
ID: id, | ||
CreatedAt: time.Now().UTC(), | ||
UpdatedAt: time.Now().UTC(), | ||
Note: params.Note, | ||
UserID: user.ID, | ||
}) | ||
if err != nil { | ||
respondWithError(w, http.StatusInternalServerError, "Couldn't create note") | ||
return | ||
} | ||
|
||
note, err := cfg.DB.GetNote(r.Context(), id) | ||
if err != nil { | ||
respondWithError(w, http.StatusNotFound, "Couldn't get note") | ||
return | ||
} | ||
respondWithJSON(w, http.StatusOK, databaseNoteToNote(note)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package main | ||
|
||
import "net/http" | ||
|
||
func handlerReadiness(w http.ResponseWriter, r *http.Request) { | ||
respondWithJSON(w, http.StatusOK, map[string]string{"status": "ok"}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package main | ||
|
||
import ( | ||
"crypto/rand" | ||
"crypto/sha256" | ||
"encoding/hex" | ||
"encoding/json" | ||
"log" | ||
"net/http" | ||
"time" | ||
|
||
"github.com/bootdotdev/learn-cicd-starter/internal/database" | ||
"github.com/google/uuid" | ||
) | ||
|
||
func (cfg *apiConfig) handlerUsersCreate(w http.ResponseWriter, r *http.Request) { | ||
type parameters struct { | ||
Name string `json:"name"` | ||
} | ||
decoder := json.NewDecoder(r.Body) | ||
params := parameters{} | ||
err := decoder.Decode(¶ms) | ||
if err != nil { | ||
respondWithError(w, http.StatusInternalServerError, "Couldn't decode parameters") | ||
return | ||
} | ||
|
||
apiKey, err := generateRandomSHA256Hash() | ||
if err != nil { | ||
respondWithError(w, http.StatusInternalServerError, "Couldn't gen apikey") | ||
return | ||
} | ||
|
||
err = cfg.DB.CreateUser(r.Context(), database.CreateUserParams{ | ||
ID: uuid.New().String(), | ||
CreatedAt: time.Now().UTC(), | ||
UpdatedAt: time.Now().UTC(), | ||
Name: params.Name, | ||
ApiKey: apiKey, | ||
}) | ||
if err != nil { | ||
log.Println(err) | ||
respondWithError(w, http.StatusInternalServerError, "Couldn't create user") | ||
return | ||
} | ||
|
||
user, err := cfg.DB.GetUserByAPIKey(r.Context(), apiKey) | ||
if err != nil { | ||
log.Println(err) | ||
respondWithError(w, http.StatusInternalServerError, "Couldn't get user") | ||
return | ||
} | ||
|
||
respondWithJSON(w, http.StatusOK, databaseUserToUser(user)) | ||
} | ||
|
||
func generateRandomSHA256Hash() (string, error) { | ||
randomBytes := make([]byte, 32) | ||
_, err := rand.Read(randomBytes) | ||
if err != nil { | ||
return "", err | ||
} | ||
hash := sha256.Sum256(randomBytes) | ||
hashString := hex.EncodeToString(hash[:]) | ||
return hashString, nil | ||
} | ||
|
||
func (cfg *apiConfig) handlerUsersGet(w http.ResponseWriter, r *http.Request, user database.User) { | ||
respondWithJSON(w, http.StatusOK, databaseUserToUser(user)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package auth | ||
|
||
import ( | ||
"errors" | ||
"net/http" | ||
"strings" | ||
) | ||
|
||
var ErrNoAuthHeaderIncluded = errors.New("no authorization header included") | ||
|
||
// GetAPIKey - | ||
func GetAPIKey(headers http.Header) (string, error) { | ||
authHeader := headers.Get("Authorization") | ||
if authHeader == "" { | ||
return "", ErrNoAuthHeaderIncluded | ||
} | ||
splitAuth := strings.Split(authHeader, " ") | ||
if len(splitAuth) < 2 || splitAuth[0] != "ApiKey" { | ||
return "", errors.New("malformed authorization header") | ||
} | ||
|
||
return splitAuth[1], nil | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.