Skip to content

Commit

Permalink
feat(oauthP): create new Style based off styleInfo
Browse files Browse the repository at this point in the history
  • Loading branch information
Gusted committed Jun 3, 2021
1 parent e736e84 commit 31813da
Show file tree
Hide file tree
Showing 6 changed files with 194 additions and 34 deletions.
75 changes: 66 additions & 9 deletions handlers/oauthProvider/authorize_style.go
@@ -1,12 +1,13 @@
package oauthprovider

import (
"fmt"
"log"
"net/url"
"time"

"github.com/form3tech-oss/jwt-go"
"github.com/gofiber/fiber/v2"
"github.com/ohler55/ojg/oj"

"userstyles.world/database"
jwtware "userstyles.world/handlers/jwt"
Expand All @@ -22,7 +23,7 @@ func AuthorizeStyleGet(c *fiber.Ctx) error {
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
c.Response().Header.Set("X-Frame-Options", "DENY")

clientID, state := c.Query("client_id"), c.Query("state")
clientID, state, styleInfo := c.Query("client_id"), c.Query("state"), c.Query("styleInfo")
if clientID == "" {
return errorMessage(c, 400, "No client_id specified")
}
Expand Down Expand Up @@ -52,10 +53,12 @@ func AuthorizeStyleGet(c *fiber.Ctx) error {
return errorMessage(c, 500, "Couldn't retrieve styles of user")
}

log.Println(styleInfo)
arguments := fiber.Map{
"User": u,
"Styles": styles,
"OAuth": OAuth,
"StyleInfo": url.QueryEscape(styleInfo),
"SecureToken": utils.PrepareText(jwt, utils.AEAD_OAUTHP),
}
for _, v := range OAuth.Scopes {
Expand All @@ -76,37 +79,37 @@ func AuthorizeStylePost(c *fiber.Ctx) error {

unsealedText, err := utils.DecodePreparedText(secureToken, utils.AEAD_OAUTHP)
if err != nil {
fmt.Println("Error: Couldn't unseal JWT Token:", err.Error())
log.Println("Error: Couldn't unseal JWT Token:", err.Error())
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
}

token, err := jwt.Parse(unsealedText, utils.OAuthPJwtKeyFunction)
if err != nil || !token.Valid {
fmt.Println("Error: Couldn't unseal JWT Token:", err.Error())
log.Println("Error: Couldn't unseal JWT Token:", err.Error())
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
}
claims := token.Claims.(jwt.MapClaims)

userID, ok := claims["userID"].(float64)
if !ok || userID != float64(u.ID) {
fmt.Println("WARNING!: Invalid userID")
log.Println("WARNING!: Invalid userID")
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
}

state, ok := claims["state"].(string)
if !ok {
fmt.Println("WARNING!: Invalid state")
log.Println("WARNING!: Invalid state")
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
}

style, err := models.GetStyleByID(database.DB, styleID)
if err != nil {
fmt.Println("Error: Style wasn't found, due to: ", err.Error())
log.Println("Error: Style wasn't found, due to: ", err.Error())
return errorMessage(c, 500, "Couldn't retrieve style of user")
}

if style.UserID != u.ID {
fmt.Println("WARNING!: Invalid style's user ID")
log.Println("WARNING!: Invalid style's user ID")
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
}

Expand All @@ -117,7 +120,7 @@ func AuthorizeStylePost(c *fiber.Ctx) error {
SetExpiration(time.Now().Add(time.Minute * 10)).
GetSignedString(utils.OAuthPSigningKey)
if err != nil {
fmt.Println("Error: Couldn't create JWT Token:", err.Error())
log.Println("Error: Couldn't create JWT Token:", err.Error())
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
}

Expand All @@ -129,3 +132,57 @@ func AuthorizeStylePost(c *fiber.Ctx) error {

return c.Redirect(OAuth.RedirectURI + "/" + returnCode)
}

// jsonParser defined options.
var jsonParser = &oj.Parser{Reuse: true}

func AuthorizeStyleNewGet(c *fiber.Ctx) error {
u, _ := jwtware.User(c)
styleInfo, oauthID, secureToken := c.Query("styleInfo"), c.Query("oauthID"), c.Query("token")

OAuth, err := models.GetOAuthByID(database.DB, oauthID)
if err != nil || OAuth.ID == 0 {
return errorMessage(c, 400, "Incorrect oauthID specified")
}

unsealedText, err := utils.DecodePreparedText(secureToken, utils.AEAD_OAUTHP)
if err != nil {
log.Println("Error: Couldn't unseal JWT Token:", err.Error())
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
}

token, err := jwt.Parse(unsealedText, utils.OAuthPJwtKeyFunction)
if err != nil || !token.Valid {
log.Println("Error: Couldn't unseal JWT Token:", err.Error())
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
}
claims := token.Claims.(jwt.MapClaims)

userID, ok := claims["userID"].(float64)
if !ok || userID != float64(u.ID) {
log.Println("WARNING!: Invalid userID")
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
}

_, ok = claims["state"].(string)
if !ok {
log.Println("WARNING!: Invalid state")
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
}

log.Println(styleInfo)
var emptyStyle models.Style
if err = jsonParser.Unmarshal(utils.UnsafeBytes(styleInfo), &emptyStyle); err != nil {
log.Println("WARNING!: Error with parsing: ", err.Error())
return errorMessage(c, 500, "JWT Token error, please notify the admins.")
}

return c.Render("add", fiber.Map{
"Title": "Add userstyle",
"User": u,
"Style": emptyStyle,
"Method": "add_api",
"OAuthID": oauthID,
"SecureToken": secureToken,
})
}
1 change: 1 addition & 0 deletions handlers/server.go
Expand Up @@ -139,6 +139,7 @@ func Initialize() {
oauthV1.Get("/authorize", jwtware.Protected, oauthprovider.AuthorizeGet)
oauthV1.Get("/authorize_style", jwtware.Protected, oauthprovider.AuthorizeStyleGet)
oauthV1.Post("/authorize_style", jwtware.Protected, oauthprovider.AuthorizeStylePost)
oauthV1.Get("/authorize_style/new", jwtware.Protected, oauthprovider.AuthorizeStyleNewGet)
oauthV1.Post("/authorize/:id/:token", jwtware.Protected, oauthprovider.AuthorizePost)
oauthV1.Post("/access_token", oauthprovider.AccessTokenPost)

Expand Down
105 changes: 99 additions & 6 deletions handlers/style/add.go
Expand Up @@ -8,19 +8,22 @@ import (
"os"
"strconv"
"strings"
"time"

"github.com/form3tech-oss/jwt-go"
"github.com/gofiber/fiber/v2"
"github.com/vednoc/go-usercss-parser"

"userstyles.world/database"
"userstyles.world/handlers/jwt"
jwtware "userstyles.world/handlers/jwt"
"userstyles.world/images"
"userstyles.world/models"
"userstyles.world/search"
"userstyles.world/utils"
)

func CreateGet(c *fiber.Ctx) error {
u, _ := jwt.User(c)
u, _ := jwtware.User(c)

return c.Render("add", fiber.Map{
"Title": "Add userstyle",
Expand All @@ -30,7 +33,8 @@ func CreateGet(c *fiber.Ctx) error {
}

func CreatePost(c *fiber.Ctx) error {
u, _ := jwt.User(c)
u, _ := jwtware.User(c)
secureToken, OAuthID := c.Query("token"), c.Query("oauthID")

// Check if userstyle name is empty.
if strings.TrimSpace(c.FormValue("name")) == "" {
Expand All @@ -54,13 +58,19 @@ func CreatePost(c *fiber.Ctx) error {

code := usercss.ParseFromString(c.FormValue("code"))
if errs := usercss.BasicMetadataValidation(code); errs != nil {
return c.Render("add", fiber.Map{
arguments := fiber.Map{
"Title": "Add userstyle",
"User": u,
"Style": s,
"Method": "add",
"Errors": errs,
})
}
if OAuthID != "" {
arguments["Method"] = "add_api"
arguments["OAuthID"] = OAuthID
arguments["SecureToken"] = secureToken
}
return c.Render("add", arguments)
}

// Prevent adding multiples of the same style.
Expand Down Expand Up @@ -94,8 +104,8 @@ func CreatePost(c *fiber.Ctx) error {
})
}

styleID := strconv.FormatUint(uint64(s.ID), 10)
if image != nil {
styleID := strconv.FormatUint(uint64(s.ID), 10)
data, _ := io.ReadAll(image)
err = os.WriteFile(images.CacheFolder+styleID+".original", data, 0o600)
if err != nil {
Expand All @@ -118,5 +128,88 @@ func CreatePost(c *fiber.Ctx) error {
log.Printf("Re-indexing style %d failed, err: %s", s.ID, err.Error())
}

if OAuthID != "" {
return handleAPIStyle(c, secureToken, OAuthID, styleID, s)
}

return c.Redirect(fmt.Sprintf("/style/%d", int(s.ID)), fiber.StatusSeeOther)
}

func handleAPIStyle(c *fiber.Ctx, secureToken, oauthID, styleID string, style *models.Style) error {
u, _ := jwtware.User(c)

OAuth, err := models.GetOAuthByID(database.DB, oauthID)
if err != nil || OAuth.ID == 0 {
return c.Status(400).
JSON(fiber.Map{
"data": "Incorrect oauthID specified",
})
}

unsealedText, err := utils.DecodePreparedText(secureToken, utils.AEAD_OAUTHP)
if err != nil {
log.Println("Error: Couldn't unseal JWT Token:", err.Error())
return c.Status(500).
JSON(fiber.Map{
"data": "JWT Token error, please notify the admins.",
})
}

token, err := jwt.Parse(unsealedText, utils.OAuthPJwtKeyFunction)
if err != nil || !token.Valid {
log.Println("Error: Couldn't unseal JWT Token:", err.Error())
return c.Status(500).
JSON(fiber.Map{
"data": "JWT Token error, please notify the admins.",
})
}
claims := token.Claims.(jwt.MapClaims)

userID, ok := claims["userID"].(float64)
if !ok || userID != float64(u.ID) {
log.Println("WARNING!: Invalid userID")
return c.Status(500).
JSON(fiber.Map{
"data": "JWT Token error, please notify the admins.",
})
}

state, ok := claims["state"].(string)
if !ok {
log.Println("WARNING!: Invalid state")
return c.Status(500).
JSON(fiber.Map{
"data": "JWT Token error, please notify the admins.",
})
}

if style.UserID != u.ID {
log.Println("WARNING!: Invalid style's user ID")
return c.Status(500).
JSON(fiber.Map{
"data": "JWT Token error, please notify the admins.",
})
}

jwt, err := utils.NewJWTToken().
SetClaim("state", state).
SetClaim("userID", u.ID).
SetClaim("styleID", style.ID).
SetExpiration(time.Now().Add(time.Minute * 10)).
GetSignedString(utils.OAuthPSigningKey)
if err != nil {
log.Println("Error: Couldn't create JWT Token:", err.Error())
return c.Status(500).
JSON(fiber.Map{
"data": "JWT Token error, please notify the admins.",
})
}

returnCode := "?code=" + utils.PrepareText(jwt, utils.AEAD_OAUTHP)
returnCode += "&style_id=" + styleID
if state != "" {
returnCode += "&state=" + state
}

return c.Redirect(OAuth.RedirectURI + "/" + returnCode)
}
5 changes: 4 additions & 1 deletion views/add.html
Expand Up @@ -3,9 +3,12 @@
{{- if eq .Method "add" -}}
{{ $method = "add" }}
{{ $btn = "Add userstyle" }}
{{ else }}
{{ else if eq .Method "edit" }}
{{ $method = printf "edit/%d" .Style.ID }}
{{ $btn = "Save changes" }}
{{ else }}
{{ $method = printf "add?token=%s&oauthID=%s" .SecureToken .OAuthID}}
{{ $btn = "Add userstyle" }}
{{ end }}

{{- $code := "" -}}
Expand Down
35 changes: 17 additions & 18 deletions views/authorize_style.html
Expand Up @@ -12,27 +12,26 @@

<section class="styles mt:l">
<h2 class="sub-title td:d">Userstyles</h2>
<p class="description">Please pick an existing style or a new style, that you'd like to link.</p>
<div class="grid flex rwrap mx:r mt:m">
{{ if ne (len .Styles) 0 }}
<p class="description">Please pick an existing style or a new style, that you'd like to link.</p>
<div class="grid flex rwrap mx:r mt:m">
{{ range .Styles }}
{{- $method := printf "api/oauth/authorize_style?styleID=%d&token=%s&oauthID=%d" .ID $.SecureToken $.OAuth.ID -}}
<div class="card col gap animate bd:o">
<div class="thumbnail">
{{ template "partials/preview_image" . }}
</div>
<div class="flex cwrap px:m bd:t fg:1 py:m">
<span class="f:h3 f:b my:0">{{- .Name -}}</span>
</div>
<form method="post" action="/{{ $method }}">
<button class="flex btn primary" type="submit">Link style</button>
</form>
{{ range .Styles }}
{{- $method := printf "api/oauth/authorize_style?styleID=%d&token=%s&oauthID=%d" .ID $.SecureToken $.OAuth.ID -}}
<div class="card col gap animate bd:o">
<div class="thumbnail">
{{ template "partials/preview_image" . }}
</div>
{{ end }}
</div>
{{ else }}
{{ template "partials/new_style" }}
<div class="flex cwrap px:m bd:t fg:1 py:m">
<span class="f:h3 f:b my:0">{{- .Name -}}</span>
</div>
<form method="post" action="/{{ $method }}">
<button class="flex btn primary" type="submit">Link style</button>
</form>
</div>
{{ end }}
{{ end }}
{{ template "partials/new_style" . }}
</div>
</section>
</div>
</main>
Expand Down
7 changes: 7 additions & 0 deletions views/partials/new_style.html
@@ -0,0 +1,7 @@
{{- $method := printf "api/oauth/authorize_style/new?styleInfo=%s&token=%s&oauthID=%d" .StyleInfo .SecureToken .OAuth.ID -}}
<div class="card col gap animate">
<a href="/{{ $method }}"
class="card-header thumbnail">
Add new style
</a>
</div>

0 comments on commit 31813da

Please sign in to comment.