mirror of
				https://github.com/zoriya/Kyoo.git
				synced 2025-10-30 18:22:41 -04:00 
			
		
		
		
	Add hurl tests for apikeys
This commit is contained in:
		
							parent
							
								
									e8acb31834
								
							
						
					
					
						commit
						dcbbb6352a
					
				| @ -99,6 +99,6 @@ RABBITMQ_DEFAULT_PASS=aohohunuhouhuhhoahothonseuhaoensuthoaentsuhha | ||||
| 
 | ||||
| # v5 stuff, does absolutely nothing on master (aka: you can delete this) | ||||
| EXTRA_CLAIMS='{"permissions": ["core.read"], "verified": false}' | ||||
| FIRST_USER_CLAIMS='{"permissions": ["users.read", "users.write", "users.delete", "core.read"], "verified": true}' | ||||
| FIRST_USER_CLAIMS='{"permissions": ["users.read", "users.write", "apikeys.read", "apikeys.write", "users.delete", "core.read", "core.write"], "verified": true}' | ||||
| GUEST_CLAIMS='{"permissions": ["core.read"]}' | ||||
| PROTECTED_CLAIMS="permissions,verified" | ||||
|  | ||||
							
								
								
									
										4
									
								
								.github/workflows/auth-hurl.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/auth-hurl.yml
									
									
									
									
										vendored
									
									
								
							| @ -53,8 +53,12 @@ jobs: | ||||
|         env: | ||||
|           POSTGRES_SERVER: localhost | ||||
|           FIRST_USER_CLAIMS: '{"permissions": ["users.read"]}' | ||||
|           KEIBI_APIKEY_HURL: 1234apikey | ||||
|           KEIBI_APIKEY_HURL_CLAIMS: '{"permissions": ["apikeys.write", "apikeys.read"]}' | ||||
| 
 | ||||
| 
 | ||||
|       - name: Show logs | ||||
|         if: failure() | ||||
|         working-directory: ./auth | ||||
|         run: cat logs | ||||
| 
 | ||||
|  | ||||
| @ -32,7 +32,7 @@ type ApiKeyWToken struct { | ||||
| } | ||||
| 
 | ||||
| type ApiKeyDto struct { | ||||
| 	Name string `json:"name" example:"my-app" validate:"alpha"` | ||||
| 	Name string `json:"name" example:"myapp" validate:"alpha"` | ||||
| 	Claims jwt.MapClaims `json:"claims" example:"isAdmin: true"` | ||||
| } | ||||
| 
 | ||||
| @ -61,8 +61,13 @@ func MapDbKey(key *dbc.Apikey) ApiKeyWToken { | ||||
| // @Failure      422  {object}  KError "Invalid create body" | ||||
| // @Router       /keys [post] | ||||
| func (h *Handler) CreateApiKey(c echo.Context) error { | ||||
| 	err := CheckPermissions(c, []string{"apikeys.write"}) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	var req ApiKeyDto | ||||
| 	err := c.Bind(&req) | ||||
| 	err = c.Bind(&req) | ||||
| 	if err != nil { | ||||
| 		return echo.NewHTTPError(http.StatusUnprocessableEntity, err.Error()) | ||||
| 	} | ||||
| @ -104,6 +109,11 @@ func (h *Handler) CreateApiKey(c echo.Context) error { | ||||
| // @Failure      422  {object}  KError "Invalid id format" | ||||
| // @Router       /keys [delete] | ||||
| func (h *Handler) DeleteApiKey(c echo.Context) error { | ||||
| 	err := CheckPermissions(c, []string{"apikeys.write"}) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	id, err := uuid.Parse(c.Param("id")) | ||||
| 	if err != nil { | ||||
| 		return echo.NewHTTPError(422, "Invalid id given: not an uuid") | ||||
| @ -127,6 +137,11 @@ func (h *Handler) DeleteApiKey(c echo.Context) error { | ||||
| // @Success      200  {object}  Page[ApiKey] | ||||
| // @Router       /keys [get] | ||||
| func (h *Handler) ListApiKey(c echo.Context) error { | ||||
| 	err := CheckPermissions(c, []string{"apikeys.read"}) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	dbkeys, err := h.db.ListApiKeys(context.Background()) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
|  | ||||
| @ -14,6 +14,7 @@ import ( | ||||
| 	"time" | ||||
| 
 | ||||
| 	"github.com/golang-jwt/jwt/v5" | ||||
| 	"github.com/google/uuid" | ||||
| 	"github.com/zoriya/kyoo/keibi/dbc" | ||||
| ) | ||||
| 
 | ||||
| @ -103,11 +104,14 @@ func LoadConfiguration(db *dbc.Queries) (*Configuration, error) { | ||||
| 	} | ||||
| 
 | ||||
| 	for _, env := range os.Environ() { | ||||
| 		if !strings.HasPrefix(env, "KEIBI_APIKEY_") || strings.HasSuffix(env, "_CLAIMS") { | ||||
| 		if !strings.HasPrefix(env, "KEIBI_APIKEY_"){ | ||||
| 			continue | ||||
| 		} | ||||
| 		v := strings.Split(env, "=") | ||||
| 		if strings.HasSuffix(v[0], "_CLAIMS") { | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		v := strings.Split(env, "=") | ||||
| 		name := strings.TrimPrefix(v[0], "KEIBI_APIKEY_") | ||||
| 		cstr := os.Getenv(fmt.Sprintf("KEIBI_APIKEY_%s_CLAIMS", name)) | ||||
| 
 | ||||
| @ -117,10 +121,14 @@ func LoadConfiguration(db *dbc.Queries) (*Configuration, error) { | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 		} else { | ||||
| 			return nil, fmt.Errorf("missing claims env var KEIBI_APIKEY_%s_CLAIMS", name) | ||||
| 		} | ||||
| 
 | ||||
| 		name = strings.ToLower(name) | ||||
| 		ret.EnvApiKeys[name] = ApiKeyWToken{ | ||||
| 			ApiKey: ApiKey{ | ||||
| 				Id: uuid.New(), | ||||
| 				Name: name, | ||||
| 				Claims: claims, | ||||
| 			}, | ||||
|  | ||||
| @ -162,7 +162,7 @@ func (h *Handler) TokenToJwt(next echo.HandlerFunc) echo.HandlerFunc { | ||||
| 		} | ||||
| 
 | ||||
| 		if jwt != nil { | ||||
| 			c.Request().Header.Set("Authorization", *jwt) | ||||
| 			c.Request().Header.Set("Authorization", fmt.Sprintf("Bearer %s", *jwt)) | ||||
| 		} | ||||
| 		return next(c) | ||||
| 	} | ||||
| @ -236,7 +236,7 @@ func main() { | ||||
| 
 | ||||
| 	r.GET("/keys", h.ListApiKey) | ||||
| 	r.POST("/keys", h.CreateApiKey) | ||||
| 	r.DELETE("/keys", h.DeleteApiKey) | ||||
| 	r.DELETE("/keys/:id", h.DeleteApiKey) | ||||
| 
 | ||||
| 	g.GET("/jwt", h.CreateJwt) | ||||
| 	e.GET("/.well-known/jwks.json", h.GetJwks) | ||||
|  | ||||
| @ -9,7 +9,7 @@ create table apikeys( | ||||
| 
 | ||||
| 	created_by integer not null references users(pk) on delete cascade, | ||||
| 	created_at timestamptz not null default now()::timestamptz, | ||||
| 	last_used timestamptz not null default now()::temistamptz | ||||
| 	last_used timestamptz not null default now()::timestamptz | ||||
| ); | ||||
| 
 | ||||
| commit; | ||||
|  | ||||
							
								
								
									
										58
									
								
								auth/tests/apikey.hurl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								auth/tests/apikey.hurl
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,58 @@ | ||||
| # perm check | ||||
| POST {{host}}/keys | ||||
| { | ||||
| 	"name": "dryflower", | ||||
| 	"claims": { | ||||
| 		"isAdmin": true, | ||||
| 		"permssions": ["core.read"] | ||||
| 	} | ||||
| } | ||||
| HTTP 401 | ||||
| 
 | ||||
| POST {{host}}/keys | ||||
| # this is created from the gh workflow file's env var | ||||
| X-API-KEY: hurl-1234apikey | ||||
| { | ||||
| 	"name": "dryflower", | ||||
| 	"claims": { | ||||
| 		"isAdmin": true, | ||||
| 		"permssions": ["core.read"] | ||||
| 	} | ||||
| } | ||||
| HTTP 201 | ||||
| [Captures] | ||||
| token: jsonpath "$.token" | ||||
| 
 | ||||
| GET {{host}}/jwt | ||||
| Authorization: Bearer {{token}} | ||||
| HTTP 200 | ||||
| [Captures] | ||||
| id: jsonpath "$.id" | ||||
| jwt: jsonpath "$.token" | ||||
| 
 | ||||
| # Duplicates email | ||||
| POST {{host}}/keys | ||||
| X-API-KEY: hurl-1234apikey | ||||
| { | ||||
| 	"name": "dryflower", | ||||
| 	"claims": { | ||||
| 		"isAdmin": true, | ||||
| 		"permssions": ["core.read"] | ||||
| 	} | ||||
| } | ||||
| HTTP 409 | ||||
| 
 | ||||
| # List | ||||
| GET {{host}}/keys | ||||
| Authorization: Bearer {{token}} | ||||
| HTTP 200 | ||||
| [Asserts] | ||||
| jsonpath "$.items[0].id" == {{id}} | ||||
| jsonpath "$.items[0].name" == "dryflower" | ||||
| jsonpath "$.items[0].claims.permissions" contains "core.read" | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| DELETE {{host}}/keys/{{id}} | ||||
| Authorization: Bearer {{jwt}} | ||||
| HTTP 200 | ||||
| @ -56,7 +56,12 @@ func GetCurrentSessionId(c echo.Context) (uuid.UUID, error) { | ||||
| 
 | ||||
| func CheckPermissions(c echo.Context, perms []string) error { | ||||
| 	token, ok := c.Get("user").(*jwt.Token) | ||||
| 	if !ok { | ||||
| 	if !ok{ | ||||
| 		return echo.NewHTTPError(401, "Not logged in") | ||||
| 	} | ||||
| 	sub, err := token.Claims.GetSubject() | ||||
| 	// ignore guests | ||||
| 	if err != nil || sub == "00000000-0000-0000-0000-000000000000" { | ||||
| 		return echo.NewHTTPError(401, "Not logged in") | ||||
| 	} | ||||
| 	claims, ok := token.Claims.(jwt.MapClaims) | ||||
| @ -68,8 +73,6 @@ func CheckPermissions(c echo.Context, perms []string) error { | ||||
| 	if !ok { | ||||
| 		return echo.NewHTTPError(403, fmt.Sprintf("Missing permissions: %s.", ", ")) | ||||
| 	} | ||||
| 	fmt.Printf("%v\n", permissions_claims) | ||||
| 	fmt.Printf("%t\n", permissions_claims) | ||||
| 	permissions_int, ok := permissions_claims.([]any) | ||||
| 	if !ok { | ||||
| 		return echo.NewHTTPError(403, "Invalid permission claim.") | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user