Skip to content

Commit 9058c25

Browse files
committed
Update
1 parent 57087b5 commit 9058c25

File tree

10 files changed

+209
-22
lines changed

10 files changed

+209
-22
lines changed

recipe/dashboard/api/implementation.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ func MakeAPIImplementation() dashboardmodels.APIInterface {
5050
}
5151
dashboardAppPath := options.AppInfo.APIBasePath.AppendPath(normalizedDashboardPath).GetAsStringDangerous()
5252

53+
authMode := string(options.Config.AuthMode)
54+
5355
return `
5456
<html>
5557
<head>
@@ -58,6 +60,7 @@ func MakeAPIImplementation() dashboardmodels.APIInterface {
5860
window.staticBasePath = "` + bundleDomain + `/static"
5961
window.dashboardAppPath = "` + dashboardAppPath + `"
6062
window.connectionURI = "` + connectionURI + `"
63+
window.authMode = "` + authMode + `"
6164
</script>
6265
<script defer src="` + bundleDomain + `/static/js/bundle.js"></script></head>
6366
<link href="` + bundleDomain + `/static/css/main.css" rel="stylesheet" type="text/css">

recipe/dashboard/api/signInPost.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package api
2+
3+
import (
4+
"encoding/json"
5+
"github.com/supertokens/supertokens-golang/recipe/dashboard/dashboardmodels"
6+
"github.com/supertokens/supertokens-golang/supertokens"
7+
)
8+
9+
type signInPostResponse struct {
10+
Status string `json:"status"`
11+
SessionId string `json:"sessionId,omitempty"`
12+
Message string `json:"message,omitempty"`
13+
}
14+
15+
type signInRequestBody struct {
16+
Email *string `json:"email"`
17+
Password *string `json:"password"`
18+
}
19+
20+
func SignInPost(apiInterface dashboardmodels.APIInterface, options dashboardmodels.APIOptions) (signInPostResponse, error) {
21+
body, err := supertokens.ReadFromRequest(options.Req)
22+
23+
if err != nil {
24+
return signInPostResponse{}, err
25+
}
26+
27+
var readBody signInRequestBody
28+
err = json.Unmarshal(body, &readBody)
29+
if err != nil {
30+
return signInPostResponse{}, err
31+
}
32+
33+
if readBody.Email == nil {
34+
return signInPostResponse{}, supertokens.BadInputError{
35+
Msg: "Required parameter 'email' is missing",
36+
}
37+
}
38+
39+
if readBody.Password == nil {
40+
return signInPostResponse{}, supertokens.BadInputError{
41+
Msg: "Required parameter 'password' is missing",
42+
}
43+
}
44+
45+
querier, querierErr := supertokens.GetNewQuerierInstanceOrThrowError("dashboard")
46+
47+
if querierErr != nil {
48+
return signInPostResponse{}, querierErr
49+
}
50+
51+
apiResponse, apiErr := querier.SendPostRequest("/recipe/dashboard/signin", map[string]interface{}{
52+
"email": *readBody.Email,
53+
"password": *readBody.Password,
54+
})
55+
56+
if apiErr != nil {
57+
return signInPostResponse{}, apiErr
58+
}
59+
60+
status, ok := apiResponse["status"]
61+
62+
if ok && status == "OK" {
63+
return signInPostResponse{
64+
Status: "OK",
65+
SessionId: apiResponse["sessionId"].(string),
66+
}, nil
67+
}
68+
69+
if status == "USER_SUSPENDED_ERROR" {
70+
return signInPostResponse{
71+
Status: "USER_SUSPENDED_ERROR",
72+
Message: apiResponse["message"].(string),
73+
}, nil
74+
}
75+
76+
return signInPostResponse{
77+
Status: "INVAlID_CREDENTIALS_ERROR",
78+
}, nil
79+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package api
2+
3+
import (
4+
"github.com/supertokens/supertokens-golang/recipe/dashboard/dashboardmodels"
5+
"github.com/supertokens/supertokens-golang/supertokens"
6+
"strings"
7+
)
8+
9+
type signOutPostResponse struct {
10+
Status string `json:"status"`
11+
}
12+
13+
func SignOutPost(apiInterface dashboardmodels.APIInterface, options dashboardmodels.APIOptions) (signOutPostResponse, error) {
14+
if options.Config.ApiKey != nil {
15+
return signOutPostResponse{
16+
Status: "OK",
17+
}, nil
18+
}
19+
20+
sessionIdFromHeader := options.Req.Header.Get("authorization")
21+
22+
// We receive the api key as `Bearer API_KEY`, this retrieves just the key
23+
keyParts := strings.Split(sessionIdFromHeader, " ")
24+
sessionIdFromHeader = keyParts[len(keyParts)-1]
25+
26+
querier, querierErr := supertokens.GetNewQuerierInstanceOrThrowError("dashboard")
27+
28+
if querierErr != nil {
29+
return signOutPostResponse{}, querierErr
30+
}
31+
32+
_, apiError := querier.SendDeleteRequest("/recipe/dashboard/session", map[string]interface{}{}, map[string]string{
33+
"sessionId": sessionIdFromHeader,
34+
})
35+
36+
if apiError != nil {
37+
return signOutPostResponse{}, apiError
38+
}
39+
40+
return signOutPostResponse{
41+
Status: "OK",
42+
}, nil
43+
}

recipe/dashboard/api/validateKey.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,22 @@ package api
22

33
import (
44
"github.com/supertokens/supertokens-golang/recipe/dashboard/dashboardmodels"
5+
"github.com/supertokens/supertokens-golang/recipe/dashboard/validationUtils"
56
"github.com/supertokens/supertokens-golang/supertokens"
67
)
78

89
func ValidateKey(apiImplementation dashboardmodels.APIInterface, options dashboardmodels.APIOptions) error {
9-
shouldAllowAccess, err := (*options.RecipeImplementation.ShouldAllowAccess)(options.Req, options.Config, supertokens.MakeDefaultUserContextFromAPI(options.Req))
10+
isKeyValid, err := validationUtils.ValidateApiKey(options.Req, options.Config, supertokens.MakeDefaultUserContextFromAPI(options.Req))
11+
1012
if err != nil {
1113
return err
1214
}
1315

14-
if !shouldAllowAccess {
16+
if isKeyValid {
17+
return supertokens.Send200Response(options.Res, map[string]interface{}{
18+
"status": "OK",
19+
})
20+
} else {
1521
return supertokens.SendUnauthorisedAccess(options.Res)
1622
}
17-
18-
return supertokens.Send200Response(options.Res, map[string]interface{}{
19-
"status": "OK",
20-
})
2123
}

recipe/dashboard/constants.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ const userSessionsAPI = "/api/user/sessions"
1010
const userMetaDataAPI = "/api/user/metadata"
1111
const userEmailVerifyTokenAPI = "/api/user/email/verify/token"
1212
const userPasswordAPI = "/api/user/password"
13+
const signInAPI = "/api/signin"
14+
const signOutAPI = "/api/signout"

recipe/dashboard/recipe.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,12 @@ func MakeRecipe(recipeId string, appInfo supertokens.NormalisedAppinfo, config *
4141
verifiedConfig := validateAndNormaliseUserInput(appInfo, config)
4242
r.Config = verifiedConfig
4343

44-
recipeImplementation := makeRecipeImplementation()
44+
querierInstance, err := supertokens.GetNewQuerierInstanceOrThrowError(recipeId)
45+
if err != nil {
46+
return Recipe{}, err
47+
}
48+
49+
recipeImplementation := makeRecipeImplementation(*querierInstance)
4550
r.RecipeImpl = verifiedConfig.Override.Functions(recipeImplementation)
4651

4752
r.APIImpl = verifiedConfig.Override.APIs(api.MakeAPIImplementation())
@@ -156,6 +161,10 @@ func (r *Recipe) handleAPIRequest(id string, req *http.Request, res http.Respons
156161
return userdetails.UserEmailVerifyTokenPost(r.APIImpl, options)
157162
} else if id == userPasswordAPI {
158163
return userdetails.UserPasswordPut(r.APIImpl, options)
164+
} else if id == signInAPI {
165+
return api.SignInPost(r.APIImpl, options)
166+
} else if id == signOutAPI {
167+
return api.SignOutPost(r.APIImpl, options)
159168
}
160169
return nil, errors.New("should never come here")
161170
})

recipe/dashboard/recipeimplementation.go

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,36 +17,46 @@ package dashboard
1717

1818
import (
1919
"fmt"
20-
"net/http"
21-
"strings"
22-
2320
"github.com/supertokens/supertokens-golang/recipe/dashboard/dashboardmodels"
21+
"github.com/supertokens/supertokens-golang/recipe/dashboard/validationUtils"
2422
"github.com/supertokens/supertokens-golang/supertokens"
23+
"net/http"
24+
"strings"
2525
)
2626

27-
func makeRecipeImplementation() dashboardmodels.RecipeInterface {
27+
func makeRecipeImplementation(querier supertokens.Querier) dashboardmodels.RecipeInterface {
2828

2929
getDashboardBundleLocation := func(userContext supertokens.UserContext) (string, error) {
3030
return fmt.Sprintf("https://cdn.jsdelivr.net/gh/supertokens/dashboard@v%s/build/", supertokens.DashboardVersion), nil
3131
}
3232

3333
shouldAllowAccess := func(req *http.Request, config dashboardmodels.TypeNormalisedInput, userContext supertokens.UserContext) (bool, error) {
3434
if config.ApiKey == nil {
35-
// TODO Handle sign in logic here
36-
return false, nil
37-
}
35+
authHeaderValue := req.Header.Get("authorization")
36+
// We receive the api key as `Bearer API_KEY`, this retrieves just the key
37+
keyParts := strings.Split(authHeaderValue, " ")
38+
authHeaderValue = keyParts[len(keyParts)-1]
39+
40+
verifyResponse, err := querier.SendPostRequest("/recipe/dashboard/session/verify", map[string]interface{}{
41+
"sessionId": authHeaderValue,
42+
})
43+
44+
if err != nil {
45+
return false, err
46+
}
3847

39-
apiKeyHeaderValue := req.Header.Get("authorization")
48+
status, ok := verifyResponse["status"]
49+
50+
return ok && status.(string) == "OK", nil
51+
}
4052

41-
// We receieve the api key as `Bearer API_KEY`, this retrieves just the key
42-
keyParts := strings.Split(apiKeyHeaderValue, " ")
43-
apiKeyHeaderValue = keyParts[len(keyParts)-1]
53+
validateKeyResponse, err := validationUtils.ValidateApiKey(req, config, userContext)
4454

45-
if apiKeyHeaderValue == "" {
46-
return false, nil
55+
if err != nil {
56+
return false, err
4757
}
4858

49-
return apiKeyHeaderValue == *config.ApiKey, nil
59+
return validateKeyResponse, nil
5060
}
5161

5262
return dashboardmodels.RecipeInterface{

recipe/dashboard/utils.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,5 +124,15 @@ func getApiIdIfMatched(path supertokens.NormalisedURLPath, method string) (*stri
124124
return &val, nil
125125
}
126126

127+
if method == http.MethodPost && strings.HasSuffix(path.GetAsStringDangerous(), signInAPI) {
128+
val := signInAPI
129+
return &val, nil
130+
}
131+
132+
if method == http.MethodPost && strings.HasSuffix(path.GetAsStringDangerous(), signOutAPI) {
133+
val := signOutAPI
134+
return &val, nil
135+
}
136+
127137
return nil, nil
128138
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package validationUtils
2+
3+
import (
4+
"github.com/supertokens/supertokens-golang/recipe/dashboard/dashboardmodels"
5+
"github.com/supertokens/supertokens-golang/supertokens"
6+
"net/http"
7+
"strings"
8+
)
9+
10+
func ValidateApiKey(req *http.Request, config dashboardmodels.TypeNormalisedInput, usercontext supertokens.UserContext) (bool, error) {
11+
apiKeyHeaderValue := req.Header.Get("authorization")
12+
13+
// We receive the api key as `Bearer API_KEY`, this retrieves just the key
14+
keyParts := strings.Split(apiKeyHeaderValue, " ")
15+
apiKeyHeaderValue = keyParts[len(keyParts)-1]
16+
17+
if apiKeyHeaderValue == "" {
18+
return false, nil
19+
}
20+
21+
return apiKeyHeaderValue == *config.ApiKey, nil
22+
}

supertokens/querier.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ func (q *Querier) SendPostRequest(path string, data map[string]interface{}) (map
144144
}, len(QuerierHosts))
145145
}
146146

147-
func (q *Querier) SendDeleteRequest(path string, data map[string]interface{}) (map[string]interface{}, error) {
147+
func (q *Querier) SendDeleteRequest(path string, data map[string]interface{}, params map[string]string) (map[string]interface{}, error) {
148148
nP, err := NewNormalisedURLPath(path)
149149
if err != nil {
150150
return nil, err
@@ -159,6 +159,13 @@ func (q *Querier) SendDeleteRequest(path string, data map[string]interface{}) (m
159159
return nil, err
160160
}
161161

162+
query := req.URL.Query()
163+
164+
for k, v := range params {
165+
query.Add(k, v)
166+
}
167+
req.URL.RawQuery = query.Encode()
168+
162169
apiVerion, querierAPIVersionError := q.GetQuerierAPIVersion()
163170
if querierAPIVersionError != nil {
164171
return nil, querierAPIVersionError

0 commit comments

Comments
 (0)