Selector param for ListChannels()
This commit is contained in:
parent
d46601be5c
commit
e8671e8650
@ -18,6 +18,7 @@ const (
|
||||
BINDFAIL_QUERY_PARAM APIError = 1151
|
||||
BINDFAIL_BODY_PARAM APIError = 1152
|
||||
BINDFAIL_URI_PARAM APIError = 1153
|
||||
INVALID_ENUM_VALUE APIError = 1171
|
||||
|
||||
NO_TITLE APIError = 1201
|
||||
TITLE_TOO_LONG APIError = 1202
|
||||
|
@ -423,10 +423,17 @@ func (h APIHandler) DeleteClient(g *gin.Context) ginresp.HTTPResponse {
|
||||
|
||||
// ListChannels swaggerdoc
|
||||
//
|
||||
// @Summary List all channels of a user
|
||||
// @Summary List channels of a user (subscribed/owned)
|
||||
// @Description The possible values for 'selector' are:
|
||||
// @Description - "owned" Return all channels of the user
|
||||
// @Description - "subscribed" Return all channels that the user is subscribing to
|
||||
// @Description - "all" Return channels that the user owns or is subscribing
|
||||
// @Description - "subscribed_any" Return all channels that the user is subscribing to (even unconfirmed)
|
||||
// @Description - "all_any" Return channels that the user owns or is subscribing (even unconfirmed)
|
||||
// @ID api-channels-list
|
||||
//
|
||||
// @Param uid path int true "UserID"
|
||||
// @Param selector query string true "Filter channels (default: owned)" Enums(owned, subscribed, all, subscribed_any, all_any)
|
||||
//
|
||||
// @Success 200 {object} handler.ListChannels.response
|
||||
// @Failure 400 {object} ginresp.apiError
|
||||
@ -439,12 +446,16 @@ func (h APIHandler) ListChannels(g *gin.Context) ginresp.HTTPResponse {
|
||||
type uri struct {
|
||||
UserID int64 `uri:"uid"`
|
||||
}
|
||||
type query struct {
|
||||
Selector *string `form:"selector"`
|
||||
}
|
||||
type response struct {
|
||||
Channels []models.ChannelJSON `json:"channels"`
|
||||
}
|
||||
|
||||
var u uri
|
||||
ctx, errResp := h.app.StartRequest(g, &u, nil, nil, nil)
|
||||
var q query
|
||||
ctx, errResp := h.app.StartRequest(g, &u, &q, nil, nil)
|
||||
if errResp != nil {
|
||||
return *errResp
|
||||
}
|
||||
@ -454,12 +465,43 @@ func (h APIHandler) ListChannels(g *gin.Context) ginresp.HTTPResponse {
|
||||
return *permResp
|
||||
}
|
||||
|
||||
clients, err := h.database.ListChannels(ctx, u.UserID)
|
||||
sel := strings.ToLower(langext.Coalesce(q.Selector, "owned"))
|
||||
|
||||
var res []models.ChannelJSON
|
||||
|
||||
if sel == "owned" {
|
||||
channels, err := h.database.ListChannelsByOwner(ctx, u.UserID)
|
||||
if err != nil {
|
||||
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to query channels", err)
|
||||
}
|
||||
|
||||
res := langext.ArrMap(clients, func(v models.Channel) models.ChannelJSON { return v.JSON() })
|
||||
res = langext.ArrMap(channels, func(v models.Channel) models.ChannelJSON { return v.JSON(true) })
|
||||
} else if sel == "subscribed_any" {
|
||||
channels, err := h.database.ListChannelsBySubscriber(ctx, u.UserID, false)
|
||||
if err != nil {
|
||||
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to query channels", err)
|
||||
}
|
||||
res = langext.ArrMap(channels, func(v models.Channel) models.ChannelJSON { return v.JSON(false) })
|
||||
} else if sel == "all_any" {
|
||||
channels, err := h.database.ListChannelsByAccess(ctx, u.UserID, false)
|
||||
if err != nil {
|
||||
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to query channels", err)
|
||||
}
|
||||
res = langext.ArrMap(channels, func(v models.Channel) models.ChannelJSON { return v.JSON(false) })
|
||||
} else if sel == "subscribed" {
|
||||
channels, err := h.database.ListChannelsBySubscriber(ctx, u.UserID, true)
|
||||
if err != nil {
|
||||
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to query channels", err)
|
||||
}
|
||||
res = langext.ArrMap(channels, func(v models.Channel) models.ChannelJSON { return v.JSON(false) })
|
||||
} else if sel == "all" {
|
||||
channels, err := h.database.ListChannelsByAccess(ctx, u.UserID, true)
|
||||
if err != nil {
|
||||
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to query channels", err)
|
||||
}
|
||||
res = langext.ArrMap(channels, func(v models.Channel) models.ChannelJSON { return v.JSON(false) })
|
||||
} else {
|
||||
return ginresp.APIError(g, 400, apierr.INVALID_ENUM_VALUE, "Invalid value for the [selector] parameter", nil)
|
||||
}
|
||||
|
||||
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, response{Channels: res}))
|
||||
}
|
||||
@ -504,7 +546,7 @@ func (h APIHandler) GetChannel(g *gin.Context) ginresp.HTTPResponse {
|
||||
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to query channel", err)
|
||||
}
|
||||
|
||||
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, channel.JSON()))
|
||||
return ctx.FinishSuccess(ginresp.JSON(http.StatusOK, channel.JSON(true)))
|
||||
}
|
||||
|
||||
// ListChannelMessages swaggerdoc
|
||||
|
@ -6,28 +6,6 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func (db *Database) GetChannelByKey(ctx TxContext, key string) (*models.Channel, error) {
|
||||
tx, err := ctx.GetOrCreateTransaction(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rows, err := tx.QueryContext(ctx, "SELECT * FROM channels WHERE subscribe_key = ? OR send_key = ? LIMIT 1", key, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
channel, err := models.DecodeChannel(rows)
|
||||
if err == sql.ErrNoRows {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &channel, nil
|
||||
}
|
||||
|
||||
func (db *Database) GetChannelByName(ctx TxContext, userid int64, chanName string) (*models.Channel, error) {
|
||||
tx, err := ctx.GetOrCreateTransaction(db)
|
||||
if err != nil {
|
||||
@ -85,7 +63,7 @@ func (db *Database) CreateChannel(ctx TxContext, userid int64, name string, subs
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (db *Database) ListChannels(ctx TxContext, userid int64) ([]models.Channel, error) {
|
||||
func (db *Database) ListChannelsByOwner(ctx TxContext, userid int64) ([]models.Channel, error) {
|
||||
tx, err := ctx.GetOrCreateTransaction(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -104,6 +82,56 @@ func (db *Database) ListChannels(ctx TxContext, userid int64) ([]models.Channel,
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (db *Database) ListChannelsBySubscriber(ctx TxContext, userid int64, confirmed bool) ([]models.Channel, error) {
|
||||
tx, err := ctx.GetOrCreateTransaction(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
confCond := ""
|
||||
if confirmed {
|
||||
confCond = " AND sub.confirmed = 1"
|
||||
}
|
||||
|
||||
rows, err := tx.QueryContext(ctx, "SELECT * FROM channels LEFT JOIN subscriptions sub on channels.channel_id = sub.channel_id WHERE sub.subscriber_user_id = ? "+confCond,
|
||||
userid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := models.DecodeChannels(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (db *Database) ListChannelsByAccess(ctx TxContext, userid int64, confirmed bool) ([]models.Channel, error) {
|
||||
tx, err := ctx.GetOrCreateTransaction(db)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
confCond := "sub.subscriber_user_id = ?"
|
||||
if confirmed {
|
||||
confCond = "(sub.subscriber_user_id = ? AND sub.confirmed = 1)"
|
||||
}
|
||||
|
||||
rows, err := tx.QueryContext(ctx, "SELECT * FROM channels LEFT JOIN subscriptions sub on channels.channel_id = sub.channel_id WHERE owner_user_id = ? OR "+confCond,
|
||||
userid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
data, err := models.DecodeChannels(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func (db *Database) GetChannel(ctx TxContext, userid int64, channelid int64) (models.Channel, error) {
|
||||
tx, err := ctx.GetOrCreateTransaction(db)
|
||||
if err != nil {
|
||||
|
@ -18,13 +18,13 @@ type Channel struct {
|
||||
MessagesSent int
|
||||
}
|
||||
|
||||
func (c Channel) JSON() ChannelJSON {
|
||||
func (c Channel) JSON(includeKey bool) ChannelJSON {
|
||||
return ChannelJSON{
|
||||
ChannelID: c.ChannelID,
|
||||
OwnerUserID: c.OwnerUserID,
|
||||
Name: c.Name,
|
||||
SubscribeKey: c.SubscribeKey,
|
||||
SendKey: c.SendKey,
|
||||
SubscribeKey: langext.Conditional(includeKey, langext.Ptr(c.SubscribeKey), nil),
|
||||
SendKey: langext.Conditional(includeKey, langext.Ptr(c.SendKey), nil),
|
||||
TimestampCreated: c.TimestampCreated.Format(time.RFC3339Nano),
|
||||
TimestampLastSent: timeOptFmt(c.TimestampLastSent, time.RFC3339Nano),
|
||||
MessagesSent: c.MessagesSent,
|
||||
@ -35,8 +35,8 @@ type ChannelJSON struct {
|
||||
ChannelID int64 `json:"channel_id"`
|
||||
OwnerUserID int64 `json:"owner_user_id"`
|
||||
Name string `json:"name"`
|
||||
SubscribeKey string `json:"subscribe_key"`
|
||||
SendKey string `json:"send_key"`
|
||||
SubscribeKey *string `json:"subscribe_key"` // can be nil, depending on endpoint
|
||||
SendKey *string `json:"send_key"` // can be nil, depending on endpoint
|
||||
TimestampCreated string `json:"timestamp_created"`
|
||||
TimestampLastSent *string `json:"timestamp_last_sent"`
|
||||
MessagesSent int `json:"messages_sent"`
|
||||
|
@ -66,6 +66,51 @@
|
||||
"schema": {
|
||||
"$ref": "#/definitions/handler.SendMessage.body"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "chan_key",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "channel",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "content",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "msg_id",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "priority",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"name": "timestamp",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "title",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "user_id",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "user_key",
|
||||
"in": "formData"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@ -167,6 +212,80 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"description": "This is similar to the main route `POST -\u003e https://scn.blackfrestbytes.com/`\nBut this route can change in the future, for long-living scripts etc. it's better to use the normal POST route",
|
||||
"summary": "Create a new message",
|
||||
"operationId": "api-messages-create",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "chan_key",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "channel",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "content",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "msg_id",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "priority",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"name": "timestamp",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "title",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "OK",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/models.MessageJSON"
|
||||
}
|
||||
},
|
||||
"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-v2/messages/{mid}": {
|
||||
@ -349,6 +468,7 @@
|
||||
},
|
||||
"/api-v2/users/{uid}/channels": {
|
||||
"get": {
|
||||
"description": "The possible values for 'selector' are:\n- \"owned\" Return all channels of the user\n- \"subscribed\" Return all channels that the user is subscribing to\n- \"all\" Return channels that the user owns or is subscribing\n- \"subscribed_any\" Return all channels that the user is subscribing to (even unconfirmed)\n- \"all_any\" Return channels that the user owns or is subscribing (even unconfirmed)",
|
||||
"summary": "List all channels of a user",
|
||||
"operationId": "api-channels-list",
|
||||
"parameters": [
|
||||
@ -358,6 +478,20 @@
|
||||
"name": "uid",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"enum": [
|
||||
"owned",
|
||||
"subscribed",
|
||||
"all",
|
||||
"subscribed_any",
|
||||
"all_any"
|
||||
],
|
||||
"type": "string",
|
||||
"description": "Filter channels (default: owned)",
|
||||
"name": "selector",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@ -1569,6 +1703,51 @@
|
||||
"schema": {
|
||||
"$ref": "#/definitions/handler.SendMessage.body"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "chan_key",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "channel",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "content",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "msg_id",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "priority",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "number",
|
||||
"name": "timestamp",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "title",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "integer",
|
||||
"name": "user_id",
|
||||
"in": "formData"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "user_key",
|
||||
"in": "formData"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@ -2049,7 +2228,7 @@
|
||||
"handler.SendMessage.body": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"chanKey": {
|
||||
"chan_key": {
|
||||
"type": "string"
|
||||
},
|
||||
"channel": {
|
||||
@ -2225,10 +2404,8 @@
|
||||
"owner_user_id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"send_key": {
|
||||
"type": "string"
|
||||
},
|
||||
"subscribe_key": {
|
||||
"description": "can be nil, depending on endpoint",
|
||||
"type": "string"
|
||||
},
|
||||
"timestamp_created": {
|
||||
|
@ -209,7 +209,7 @@ definitions:
|
||||
type: object
|
||||
handler.SendMessage.body:
|
||||
properties:
|
||||
chanKey:
|
||||
chan_key:
|
||||
type: string
|
||||
channel:
|
||||
type: string
|
||||
@ -324,9 +324,8 @@ definitions:
|
||||
type: string
|
||||
owner_user_id:
|
||||
type: integer
|
||||
send_key:
|
||||
type: string
|
||||
subscribe_key:
|
||||
description: can be nil, depending on endpoint
|
||||
type: string
|
||||
timestamp_created:
|
||||
type: string
|
||||
@ -480,6 +479,33 @@ paths:
|
||||
name: post_body
|
||||
schema:
|
||||
$ref: '#/definitions/handler.SendMessage.body'
|
||||
- in: formData
|
||||
name: chan_key
|
||||
type: string
|
||||
- in: formData
|
||||
name: channel
|
||||
type: string
|
||||
- in: formData
|
||||
name: content
|
||||
type: string
|
||||
- in: formData
|
||||
name: msg_id
|
||||
type: string
|
||||
- in: formData
|
||||
name: priority
|
||||
type: integer
|
||||
- in: formData
|
||||
name: timestamp
|
||||
type: number
|
||||
- in: formData
|
||||
name: title
|
||||
type: string
|
||||
- in: formData
|
||||
name: user_id
|
||||
type: integer
|
||||
- in: formData
|
||||
name: user_key
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
@ -549,6 +575,55 @@ paths:
|
||||
schema:
|
||||
$ref: '#/definitions/ginresp.apiError'
|
||||
summary: List all (subscribed) messages
|
||||
post:
|
||||
description: |-
|
||||
This is similar to the main route `POST -> https://scn.blackfrestbytes.com/`
|
||||
But this route can change in the future, for long-living scripts etc. it's better to use the normal POST route
|
||||
operationId: api-messages-create
|
||||
parameters:
|
||||
- in: query
|
||||
name: chan_key
|
||||
type: string
|
||||
- in: query
|
||||
name: channel
|
||||
type: string
|
||||
- in: query
|
||||
name: content
|
||||
type: string
|
||||
- in: query
|
||||
name: msg_id
|
||||
type: string
|
||||
- in: query
|
||||
name: priority
|
||||
type: integer
|
||||
- in: query
|
||||
name: timestamp
|
||||
type: number
|
||||
- in: query
|
||||
name: title
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
schema:
|
||||
$ref: '#/definitions/models.MessageJSON'
|
||||
"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: Create a new message
|
||||
/api-v2/messages/{mid}:
|
||||
patch:
|
||||
description: The user must own the message and request the resource with the
|
||||
@ -669,6 +744,13 @@ paths:
|
||||
summary: (Partially) update a user
|
||||
/api-v2/users/{uid}/channels:
|
||||
get:
|
||||
description: |-
|
||||
The possible values for 'selector' are:
|
||||
- "owned" Return all channels of the user
|
||||
- "subscribed" Return all channels that the user is subscribing to
|
||||
- "all" Return channels that the user owns or is subscribing
|
||||
- "subscribed_any" Return all channels that the user is subscribing to (even unconfirmed)
|
||||
- "all_any" Return channels that the user owns or is subscribing (even unconfirmed)
|
||||
operationId: api-channels-list
|
||||
parameters:
|
||||
- description: UserID
|
||||
@ -676,6 +758,17 @@ paths:
|
||||
name: uid
|
||||
required: true
|
||||
type: integer
|
||||
- description: 'Filter channels (default: owned)'
|
||||
enum:
|
||||
- owned
|
||||
- subscribed
|
||||
- all
|
||||
- subscribed_any
|
||||
- all_any
|
||||
in: query
|
||||
name: selector
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
@ -1489,6 +1582,33 @@ paths:
|
||||
name: post_body
|
||||
schema:
|
||||
$ref: '#/definitions/handler.SendMessage.body'
|
||||
- in: formData
|
||||
name: chan_key
|
||||
type: string
|
||||
- in: formData
|
||||
name: channel
|
||||
type: string
|
||||
- in: formData
|
||||
name: content
|
||||
type: string
|
||||
- in: formData
|
||||
name: msg_id
|
||||
type: string
|
||||
- in: formData
|
||||
name: priority
|
||||
type: integer
|
||||
- in: formData
|
||||
name: timestamp
|
||||
type: number
|
||||
- in: formData
|
||||
name: title
|
||||
type: string
|
||||
- in: formData
|
||||
name: user_id
|
||||
type: integer
|
||||
- in: formData
|
||||
name: user_key
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: OK
|
||||
|
Loading…
Reference in New Issue
Block a user