ListClients()
This commit is contained in:
parent
35ef2175bc
commit
f555f0f1cf
@ -28,7 +28,8 @@ build-docker:
|
||||
-t "$(DOCKER_REPO)/$(DOCKER_NAME):latest" \
|
||||
.
|
||||
|
||||
build-swagger:
|
||||
.PHONY: swagger
|
||||
swagger:
|
||||
which swag || go install github.com/swaggo/swag/cmd/swag@latest
|
||||
swag init -generalInfo api/router.go --output ./swagger/ --outputTypes "json,yaml"
|
||||
|
||||
|
@ -96,7 +96,7 @@ func (h APIHandler) CreateUser(g *gin.Context) ginresp.HTTPResponse {
|
||||
|
||||
// GetUser swaggerdoc
|
||||
//
|
||||
// @Summary Get a user (only self is allowed)
|
||||
// @Summary Get a user
|
||||
// @ID api-user-get
|
||||
//
|
||||
// @Param uid path int true "UserID"
|
||||
@ -137,7 +137,7 @@ func (h APIHandler) GetUser(g *gin.Context) ginresp.HTTPResponse {
|
||||
|
||||
// UpdateUser swaggerdoc
|
||||
//
|
||||
// @Summary (Partially) update a user (only self allowed)
|
||||
// @Summary (Partially) update a user
|
||||
// @Description The body-values are optional, only send the ones you want to update
|
||||
// @ID api-user-update
|
||||
//
|
||||
@ -212,8 +212,47 @@ func (h APIHandler) UpdateUser(g *gin.Context) ginresp.HTTPResponse {
|
||||
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, user.JSON()))
|
||||
}
|
||||
|
||||
// ListClients swaggerdoc
|
||||
//
|
||||
// @Summary List all clients
|
||||
// @ID api-clients-list
|
||||
//
|
||||
// @Param uid path int true "UserID"
|
||||
//
|
||||
// @Success 200 {object} handler.ListClients.result
|
||||
// @Failure 400 {object} ginresp.apiError
|
||||
// @Failure 401 {object} ginresp.apiError
|
||||
// @Failure 404 {object} ginresp.apiError
|
||||
// @Failure 500 {object} ginresp.apiError
|
||||
//
|
||||
// @Router /api-v2/user/{uid}/clients [GET]
|
||||
func (h APIHandler) ListClients(g *gin.Context) ginresp.HTTPResponse {
|
||||
return ginresp.NotImplemented()
|
||||
type uri struct {
|
||||
UserID int64 `uri:"uid"`
|
||||
}
|
||||
type result struct {
|
||||
Clients []models.ClientJSON `json:"clients"`
|
||||
}
|
||||
|
||||
var u uri
|
||||
ctx, errResp := h.app.StartRequest(g, &u, nil, nil)
|
||||
if errResp != nil {
|
||||
return *errResp
|
||||
}
|
||||
defer ctx.Cancel()
|
||||
|
||||
if permResp := ctx.CheckPermissionUserRead(u.UserID); permResp != nil {
|
||||
return *permResp
|
||||
}
|
||||
|
||||
clients, err := h.app.Database.ListClients(ctx, u.UserID)
|
||||
if err != nil {
|
||||
return ginresp.InternAPIError(500, apierr.DATABASE_ERROR, "Failed to query user", err)
|
||||
}
|
||||
|
||||
res := langext.ArrMap(clients, func(v models.Client) models.ClientJSON { return v.JSON() })
|
||||
|
||||
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, result{Clients: res}))
|
||||
}
|
||||
|
||||
func (h APIHandler) GetClient(g *gin.Context) ginresp.HTTPResponse {
|
||||
|
@ -3,6 +3,7 @@ package models
|
||||
import (
|
||||
"database/sql"
|
||||
"github.com/blockloop/scan"
|
||||
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -71,10 +72,19 @@ func (c ChannelDB) Model() Channel {
|
||||
}
|
||||
|
||||
func DecodeChannel(r *sql.Rows) (Channel, error) {
|
||||
var udb ChannelDB
|
||||
err := scan.RowStrict(&udb, r)
|
||||
var data ChannelDB
|
||||
err := scan.RowStrict(&data, r)
|
||||
if err != nil {
|
||||
return Channel{}, err
|
||||
}
|
||||
return udb.Model(), nil
|
||||
return data.Model(), nil
|
||||
}
|
||||
|
||||
func DecodeChannels(r *sql.Rows) ([]Channel, error) {
|
||||
var data []ChannelDB
|
||||
err := scan.RowsStrict(&data, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return langext.ArrMap(data, func(v ChannelDB) Channel { return v.Model() }), nil
|
||||
}
|
||||
|
@ -1,6 +1,11 @@
|
||||
package models
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"database/sql"
|
||||
"github.com/blockloop/scan"
|
||||
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ClientType string
|
||||
|
||||
@ -19,5 +24,64 @@ type Client struct {
|
||||
AgentVersion string
|
||||
}
|
||||
|
||||
type ClientJSON struct {
|
||||
func (c Client) JSON() ClientJSON {
|
||||
return ClientJSON{
|
||||
ClientID: c.ClientID,
|
||||
UserID: c.UserID,
|
||||
Type: c.Type,
|
||||
FCMToken: c.FCMToken,
|
||||
TimestampCreated: c.TimestampCreated.Format(time.RFC3339Nano),
|
||||
AgentModel: c.AgentModel,
|
||||
AgentVersion: c.AgentVersion,
|
||||
}
|
||||
}
|
||||
|
||||
type ClientJSON struct {
|
||||
ClientID int64 `json:"client_id"`
|
||||
UserID int64 `json:"user_id"`
|
||||
Type ClientType `json:"type"`
|
||||
FCMToken *string `json:"fcm_token"`
|
||||
TimestampCreated string `json:"timestamp_created"`
|
||||
AgentModel string `json:"agent_model"`
|
||||
AgentVersion string `json:"agent_version"`
|
||||
}
|
||||
|
||||
type ClientDB struct {
|
||||
ClientID int64 `db:"client_id"`
|
||||
UserID int64 `db:"user_id"`
|
||||
Type ClientType `db:"type"`
|
||||
FCMToken *string `db:"fcm_token"`
|
||||
TimestampCreated int64 `db:"timestamp_created"`
|
||||
AgentModel string `db:"agent_model"`
|
||||
AgentVersion string `db:"agent_version"`
|
||||
}
|
||||
|
||||
func (c ClientDB) Model() Client {
|
||||
return Client{
|
||||
ClientID: c.ClientID,
|
||||
UserID: c.UserID,
|
||||
Type: c.Type,
|
||||
FCMToken: c.FCMToken,
|
||||
TimestampCreated: time.UnixMilli(c.TimestampCreated),
|
||||
AgentModel: c.AgentModel,
|
||||
AgentVersion: c.AgentVersion,
|
||||
}
|
||||
}
|
||||
|
||||
func DecodeClient(r *sql.Rows) (Client, error) {
|
||||
var data ClientDB
|
||||
err := scan.RowStrict(&data, r)
|
||||
if err != nil {
|
||||
return Client{}, err
|
||||
}
|
||||
return data.Model(), nil
|
||||
}
|
||||
|
||||
func DecodeClients(r *sql.Rows) ([]Client, error) {
|
||||
var data []ClientDB
|
||||
err := scan.RowsStrict(&data, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return langext.ArrMap(data, func(v ClientDB) Client { return v.Model() }), nil
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package models
|
||||
import (
|
||||
"database/sql"
|
||||
"github.com/blockloop/scan"
|
||||
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -88,10 +89,19 @@ func (u UserDB) Model() User {
|
||||
}
|
||||
|
||||
func DecodeUser(r *sql.Rows) (User, error) {
|
||||
var udb UserDB
|
||||
err := scan.RowStrict(&udb, r)
|
||||
var data UserDB
|
||||
err := scan.RowStrict(&data, r)
|
||||
if err != nil {
|
||||
return User{}, err
|
||||
}
|
||||
return udb.Model(), nil
|
||||
return data.Model(), nil
|
||||
}
|
||||
|
||||
func DecodeUsers(r *sql.Rows) ([]User, error) {
|
||||
var data []UserDB
|
||||
err := scan.RowsStrict(&data, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return langext.ArrMap(data, func(v UserDB) User { return v.Model() }), nil
|
||||
}
|
||||
|
@ -8,13 +8,17 @@ func Wrap(fn WHandlerFunc) gin.HandlerFunc {
|
||||
|
||||
return func(g *gin.Context) {
|
||||
|
||||
reqctx := g.Request.Context()
|
||||
|
||||
wrap := fn(g)
|
||||
|
||||
if g.Writer.Written() {
|
||||
panic("Writing in WrapperFunc is not supported")
|
||||
}
|
||||
|
||||
if reqctx.Err() == nil {
|
||||
wrap.Write(g)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -202,3 +202,22 @@ func (db *Database) UpdateUserProToken(ctx TxContext, userid int64, protoken *st
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *Database) ListClients(ctx TxContext, userid int64) ([]models.Client, error) {
|
||||
tx, err := ctx.GetOrCreateTransaction(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rows, err := tx.QueryContext(ctx, "SELECT * FROM clients WHERE user_id = ?", userid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := models.DecodeClients(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ require (
|
||||
github.com/gin-gonic/gin v1.8.1
|
||||
github.com/rs/zerolog v1.28.0
|
||||
github.com/swaggo/swag v1.8.7
|
||||
gogs.mikescher.com/BlackForestBytes/goext v0.0.18
|
||||
)
|
||||
|
||||
require (
|
||||
@ -33,7 +34,6 @@ require (
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.7 // indirect
|
||||
gogs.mikescher.com/BlackForestBytes/goext v0.0.17 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
|
||||
golang.org/x/sys v0.1.0 // indirect
|
||||
|
@ -95,6 +95,8 @@ github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0
|
||||
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
||||
gogs.mikescher.com/BlackForestBytes/goext v0.0.17 h1:jsfbvII7aa0SH9qY0fnXBdtNnQe1YY3DgXDThEwLICc=
|
||||
gogs.mikescher.com/BlackForestBytes/goext v0.0.17/go.mod h1:TMBOjo3FRFh/GiTT0z3nwLmgcFJB87oSF2VMs4XUCTQ=
|
||||
gogs.mikescher.com/BlackForestBytes/goext v0.0.18 h1:fprrLoAPGdI4ObveHR1DjiP9WhlTJppWtjqMA6ZkyS8=
|
||||
gogs.mikescher.com/BlackForestBytes/goext v0.0.18/go.mod h1:TMBOjo3FRFh/GiTT0z3nwLmgcFJB87oSF2VMs4XUCTQ=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||
|
@ -43,7 +43,7 @@ func (app *Application) Run() {
|
||||
errChan := make(chan error)
|
||||
|
||||
go func() {
|
||||
log.Info().Str("address", httpserver.Addr).Msg("HTTP-Server started")
|
||||
log.Info().Str("address", httpserver.Addr).Msg("HTTP-Server started on http://localhost:" + app.Config.ServerPort)
|
||||
errChan <- httpserver.ListenAndServe()
|
||||
}()
|
||||
|
||||
|
@ -47,7 +47,7 @@
|
||||
},
|
||||
"/api-v2/user/{uid}": {
|
||||
"get": {
|
||||
"summary": "Get a user (only self is allowed)",
|
||||
"summary": "Get a user",
|
||||
"operationId": "api-user-get",
|
||||
"parameters": [
|
||||
{
|
||||
@ -93,7 +93,7 @@
|
||||
},
|
||||
"patch": {
|
||||
"description": "The body-values are optional, only send the ones you want to update",
|
||||
"summary": "(Partially) update a user (only self allowed)",
|
||||
"summary": "(Partially) update a user",
|
||||
"operationId": "api-user-update",
|
||||
"parameters": [
|
||||
{
|
||||
@ -139,6 +139,53 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api-v2/user/{uid}/clients": {
|
||||
"get": {
|
||||
"summary": "List all clients",
|
||||
"operationId": "api-clients-list",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "integer",
|
||||
"description": "UserID",
|
||||
"name": "uid",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/handler.ListClients.result"
|
||||
}
|
||||
},
|
||||
"400": {
|
||||
"description": "Bad Request",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ginresp.apiError"
|
||||
}
|
||||
},
|
||||
"401": {
|
||||
"description": "Unauthorized",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ginresp.apiError"
|
||||
}
|
||||
},
|
||||
"404": {
|
||||
"description": "Not Found",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ginresp.apiError"
|
||||
}
|
||||
},
|
||||
"500": {
|
||||
"description": "Internal Server Error",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/ginresp.apiError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/ack.php": {
|
||||
"get": {
|
||||
"summary": "Acknowledge that a message was received",
|
||||
@ -667,6 +714,17 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"handler.ListClients.result": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"clients": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/models.ClientJSON"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"handler.Register.response": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@ -801,6 +859,32 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.ClientJSON": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"agent_model": {
|
||||
"type": "string"
|
||||
},
|
||||
"agent_version": {
|
||||
"type": "string"
|
||||
},
|
||||
"client_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"fcm_token": {
|
||||
"type": "string"
|
||||
},
|
||||
"timestamp_created": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
},
|
||||
"user_id": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"models.CompatMessage": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
@ -84,6 +84,13 @@ definitions:
|
||||
user_key:
|
||||
type: string
|
||||
type: object
|
||||
handler.ListClients.result:
|
||||
properties:
|
||||
clients:
|
||||
items:
|
||||
$ref: '#/definitions/models.ClientJSON'
|
||||
type: array
|
||||
type: object
|
||||
handler.Register.response:
|
||||
properties:
|
||||
is_pro:
|
||||
@ -171,6 +178,23 @@ definitions:
|
||||
uri:
|
||||
type: string
|
||||
type: object
|
||||
models.ClientJSON:
|
||||
properties:
|
||||
agent_model:
|
||||
type: string
|
||||
agent_version:
|
||||
type: string
|
||||
client_id:
|
||||
type: integer
|
||||
fcm_token:
|
||||
type: string
|
||||
timestamp_created:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
user_id:
|
||||
type: integer
|
||||
type: object
|
||||
models.CompatMessage:
|
||||
properties:
|
||||
body:
|
||||
@ -290,7 +314,7 @@ paths:
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/ginresp.apiError'
|
||||
summary: Get a user (only self is allowed)
|
||||
summary: Get a user
|
||||
patch:
|
||||
description: The body-values are optional, only send the ones you want to update
|
||||
operationId: api-user-update
|
||||
@ -321,7 +345,38 @@ paths:
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/ginresp.apiError'
|
||||
summary: (Partially) update a user (only self allowed)
|
||||
summary: (Partially) update a user
|
||||
/api-v2/user/{uid}/clients:
|
||||
get:
|
||||
operationId: api-clients-list
|
||||
parameters:
|
||||
- description: UserID
|
||||
in: path
|
||||
name: uid
|
||||
required: true
|
||||
type: integer
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/handler.ListClients.result'
|
||||
"400":
|
||||
description: Bad Request
|
||||
schema:
|
||||
$ref: '#/definitions/ginresp.apiError'
|
||||
"401":
|
||||
description: Unauthorized
|
||||
schema:
|
||||
$ref: '#/definitions/ginresp.apiError'
|
||||
"404":
|
||||
description: Not Found
|
||||
schema:
|
||||
$ref: '#/definitions/ginresp.apiError'
|
||||
"500":
|
||||
description: Internal Server Error
|
||||
schema:
|
||||
$ref: '#/definitions/ginresp.apiError'
|
||||
summary: List all clients
|
||||
/api/ack.php:
|
||||
get:
|
||||
operationId: compat-ack
|
||||
|
Loading…
Reference in New Issue
Block a user