Add /users/:username in keibi

This commit is contained in:
Zoe Roux 2025-04-06 23:42:34 +02:00
parent 4b0100c52d
commit 18eb1b02a3
No known key found for this signature in database
6 changed files with 75 additions and 17 deletions

View File

@ -52,6 +52,7 @@ jobs:
hurl --error-format long --variable host=http://localhost:4568 tests/*
env:
POSTGRES_SERVER: localhost
FIRST_USER_CLAIMS: '{"permissions": ["users.read"]}'
- name: Show logs
working-directory: ./auth

View File

@ -175,10 +175,18 @@ select
from
users as u
left join oidc_handle as h on u.pk = h.user_pk
where
u.id = $1
where ($1::boolean
and u.id = $2)
or (not $1
and u.username = $3)
`
type GetUserParams struct {
UseId bool `json:"useId"`
Id uuid.UUID `json:"id"`
Username string `json:"username"`
}
type GetUserRow struct {
User User `json:"user"`
Provider *string `json:"provider"`
@ -187,8 +195,8 @@ type GetUserRow struct {
ProfileUrl *string `json:"profileUrl"`
}
func (q *Queries) GetUser(ctx context.Context, id uuid.UUID) ([]GetUserRow, error) {
rows, err := q.db.Query(ctx, getUser, id)
func (q *Queries) GetUser(ctx context.Context, arg GetUserParams) ([]GetUserRow, error) {
rows, err := q.db.Query(ctx, getUser, arg.UseId, arg.Id, arg.Username)
if err != nil {
return nil, err
}

View File

@ -28,8 +28,10 @@ select
from
users as u
left join oidc_handle as h on u.pk = h.user_pk
where
u.id = $1;
where (@use_id::boolean
and u.id = @id)
or (not @use_id
and u.username = @username);
-- name: GetUserByLogin :one
select

View File

@ -15,6 +15,15 @@ HTTP 200
[Captures]
jwt: jsonpath "$.token"
GET {{host}}/users/me
Authorization: Bearer {{jwt}}
HTTP 200
[Captures]
userId: jsonpath "$.id"
[Asserts]
# this should be defined in the `FIRST_USER_CLAIMS='{"permissions": ["users.read"]}'` env var
jsonpath "$.claims.permissions" contains "users.read"
# Duplicates usernames
POST {{host}}/users
@ -35,6 +44,26 @@ POST {{host}}/users
}
HTTP 409
# Cannot get non-existing user
GET {{host}}/users/dont-exist
Authorization: Bearer {{jwt}}
HTTP 404
# Can get user by id
GET {{host}}/users/{{userId}}
Authorization: Bearer {{jwt}}
HTTP 200
[Asserts]
jsonpath "$.username" == "user-1"
# Can get user by username
GET {{host}}/users/user-1
Authorization: Bearer {{jwt}}
HTTP 200
[Asserts]
jsonpath "$.id" == {{userId}}
jsonpath "$.username" == "user-1"
DELETE {{host}}/users/me
Authorization: Bearer {{jwt}}

View File

@ -94,7 +94,7 @@ func MapOidc(oidc *dbc.GetUserRow) OidcHandle {
// @Failure 422 {object} KError "Invalid after id"
// @Router /users [get]
func (h *Handler) ListUsers(c echo.Context) error {
err := CheckPermissions(c, []string{"user.read"})
err := CheckPermissions(c, []string{"users.read"})
if err != nil {
return err
}
@ -139,19 +139,24 @@ func (h *Handler) ListUsers(c echo.Context) error {
// @Failure 422 {object} KError "Invalid id (not a uuid)"
// @Router /users/{id} [get]
func (h *Handler) GetUser(c echo.Context) error {
err := CheckPermissions(c, []string{"user.read"})
err := CheckPermissions(c, []string{"users.read"})
if err != nil {
return err
}
id, err := uuid.Parse(c.Param("id"))
if err != nil {
return echo.NewHTTPError(http.StatusUnprocessableEntity, "Invalid id")
}
dbuser, err := h.db.GetUser(context.Background(), id)
id := c.Param("id")
uid, err := uuid.Parse(c.Param("id"))
dbuser, err := h.db.GetUser(context.Background(), dbc.GetUserParams{
UseId: err == nil,
Id: uid,
Username: id,
})
if err != nil {
return err
}
if len(dbuser) == 0 {
return echo.NewHTTPError(404, fmt.Sprintf("No user found with id or username: '%s'.", id))
}
user := MapDbUser(&dbuser[0].User)
for _, oidc := range dbuser {
@ -177,7 +182,10 @@ func (h *Handler) GetMe(c echo.Context) error {
if err != nil {
return err
}
dbuser, err := h.db.GetUser(context.Background(), id)
dbuser, err := h.db.GetUser(context.Background(), dbc.GetUserParams{
UseId: true,
Id: id,
})
if err != nil {
return err
}
@ -246,7 +254,7 @@ func (h *Handler) Register(c echo.Context) error {
// @Failure 404 {object} KError "Invalid user id"
// @Router /users/{id} [delete]
func (h *Handler) DeleteUser(c echo.Context) error {
err := CheckPermissions(c, []string{"user.delete"})
err := CheckPermissions(c, []string{"users.delete"})
if err != nil {
return err
}
@ -348,7 +356,7 @@ func (h *Handler) EditSelf(c echo.Context) error {
// @Success 422 {object} KError "Invalid body"
// @Router /users/{id} [patch]
func (h *Handler) EditUser(c echo.Context) error {
err := CheckPermissions(c, []string{"user.write"})
err := CheckPermissions(c, []string{"users.write"})
if err != nil {
return err
}

View File

@ -68,11 +68,21 @@ func CheckPermissions(c echo.Context, perms []string) error {
if !ok {
return echo.NewHTTPError(403, fmt.Sprintf("Missing permissions: %s.", ", "))
}
permissions, ok := permissions_claims.([]string)
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.")
}
permissions := make([]string, len(permissions_int))
for i, perm := range permissions_int {
permissions[i], ok = perm.(string)
if !ok {
return echo.NewHTTPError(403, "Invalid permission claim.")
}
}
missing := make([]string, 0)
for _, perm := range perms {
if !slices.Contains(permissions, perm) {