Refactor client.descriptionName to client.name

This commit is contained in:
Mike Schwörer 2024-06-01 13:45:28 +02:00
parent 189c3ab273
commit 16d97ad08f
Signed by: Mikescher
GPG Key ID: D3C7172E0A70F8CF
12 changed files with 356 additions and 87 deletions

View File

@ -122,7 +122,7 @@ func (h APIHandler) AddClient(g *gin.Context) ginresp.HTTPResponse {
FCMToken string `json:"fcm_token" binding:"required"`
AgentModel string `json:"agent_model" binding:"required"`
AgentVersion string `json:"agent_version" binding:"required"`
DescriptionName *string `json:"description_name"`
Name *string `json:"name"`
ClientType models.ClientType `json:"client_type" binding:"required"`
}
@ -148,7 +148,7 @@ func (h APIHandler) AddClient(g *gin.Context) ginresp.HTTPResponse {
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to delete existing clients in db", err)
}
client, err := h.database.CreateClient(ctx, u.UserID, clientType, b.FCMToken, b.AgentModel, b.AgentVersion, b.DescriptionName)
client, err := h.database.CreateClient(ctx, u.UserID, clientType, b.FCMToken, b.AgentModel, b.AgentVersion, b.Name)
if err != nil {
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to create client in db", err)
}
@ -234,7 +234,7 @@ func (h APIHandler) UpdateClient(g *gin.Context) ginresp.HTTPResponse {
FCMToken *string `json:"fcm_token"`
AgentModel *string `json:"agent_model"`
AgentVersion *string `json:"agent_version"`
DescriptionName *string `json:"description_name"`
Name *string `json:"name"`
}
var u uri
@ -284,14 +284,14 @@ func (h APIHandler) UpdateClient(g *gin.Context) ginresp.HTTPResponse {
}
}
if b.DescriptionName != nil {
if *b.DescriptionName == "" {
if b.Name != nil {
if *b.Name == "" {
err = h.database.UpdateClientDescriptionName(ctx, u.ClientID, nil)
if err != nil {
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to update client", err)
}
} else {
err = h.database.UpdateClientDescriptionName(ctx, u.ClientID, langext.Ptr(*b.DescriptionName))
err = h.database.UpdateClientDescriptionName(ctx, u.ClientID, langext.Ptr(*b.Name))
if err != nil {
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to update client", err)
}

View File

@ -33,7 +33,7 @@ func (h APIHandler) CreateUser(g *gin.Context) ginresp.HTTPResponse {
Username *string `json:"username"`
AgentModel string `json:"agent_model"`
AgentVersion string `json:"agent_version"`
DescriptionName *string `json:"description_name"`
ClientName *string `json:"client_name"`
ClientType models.ClientType `json:"client_type"`
NoClient bool `json:"no_client"`
}
@ -124,7 +124,7 @@ func (h APIHandler) CreateUser(g *gin.Context) ginresp.HTTPResponse {
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to delete existing clients in db", err)
}
client, err := h.database.CreateClient(ctx, userobj.UserID, clientType, b.FCMToken, b.AgentModel, b.AgentVersion, b.DescriptionName)
client, err := h.database.CreateClient(ctx, userobj.UserID, clientType, b.FCMToken, b.AgentModel, b.AgentVersion, b.ClientName)
if err != nil {
return ginresp.APIError(g, 500, apierr.DATABASE_ERROR, "Failed to create client in db", err)
}

View File

@ -7,7 +7,7 @@ import (
"time"
)
func (db *Database) CreateClient(ctx db.TxContext, userid models.UserID, ctype models.ClientType, fcmToken string, agentModel string, agentVersion string, descriptionName *string) (models.Client, error) {
func (db *Database) CreateClient(ctx db.TxContext, userid models.UserID, ctype models.ClientType, fcmToken string, agentModel string, agentVersion string, name *string) (models.Client, error) {
tx, err := ctx.GetOrCreateTransaction(db)
if err != nil {
return models.Client{}, err
@ -21,7 +21,7 @@ func (db *Database) CreateClient(ctx db.TxContext, userid models.UserID, ctype m
TimestampCreated: time2DB(time.Now()),
AgentModel: agentModel,
AgentVersion: agentVersion,
DescriptionName: descriptionName,
Name: name,
}
_, err = sq.InsertSingle(ctx, tx, "clients", entity)
@ -172,7 +172,7 @@ func (db *Database) UpdateClientDescriptionName(ctx db.TxContext, clientid model
return err
}
_, err = tx.Exec(ctx, "UPDATE clients SET description_name = :vvv WHERE client_id = :cid", sq.PP{
_, err = tx.Exec(ctx, "UPDATE clients SET name = :vvv WHERE client_id = :cid", sq.PP{
"vvv": descriptionName,
"cid": clientid,
})

View File

@ -40,7 +40,7 @@ var PrimarySchema = map[int]Def{
2: {primarySchema2, "07ed1449114416ed043084a30e0722a5f97bf172161338d2f7106a8dfd387d0a"},
3: {primarySchema3, "65c2125ad0e12d02490cf2275f0067ef3c62a8522edf9a35ee8aa3f3c09b12e8"},
4: {primarySchema4, "cb022156ab0e7aea39dd0c985428c43cae7d60e41ca8e9e5a84c774b3019d2ca"},
5: {primarySchema5, "04bd0d4a81540f69f10c8f8cd656a1fdf852d4ef7a2ab2918ca6369b5423b1b6"},
5: {primarySchema5, "9d6217ba4a3503cfe090f72569367f95a413bb14e9effe49ffeabbf255bce8dd"},
}
var PrimarySchemaVersion = 5

View File

@ -49,9 +49,9 @@ CREATE TABLE clients
client_id TEXT NOT NULL,
user_id TEXT NOT NULL,
type TEXT CHECK(type IN ('ANDROID', 'IOS')) NOT NULL,
type TEXT CHECK(type IN ('ANDROID','IOS','LINUX','MACOS','WINDOWS')) NOT NULL,
fcm_token TEXT NOT NULL,
description_name TEXT NULL,
name TEXT NULL,
timestamp_created INTEGER NOT NULL,

View File

@ -1,6 +1,32 @@
ALTER TABLE clients ADD COLUMN "description_name" TEXT NULL;
ALTER TABLE clients ADD COLUMN "name" TEXT NULL;
DROP INDEX "idx_clients_userid";
DROP INDEX "idx_clients_fcmtoken";
CREATE TABLE clients_new
(
client_id TEXT NOT NULL,
user_id TEXT NOT NULL,
type TEXT CHECK(type IN ('ANDROID','IOS','LINUX','MACOS','WINDOWS')) NOT NULL,
fcm_token TEXT NOT NULL,
name TEXT NULL,
timestamp_created INTEGER NOT NULL,
agent_model TEXT NOT NULL,
agent_version TEXT NOT NULL,
PRIMARY KEY (client_id)
) STRICT;
INSERT INTO clients_new SELECT * FROM clients;
DROP TABLE clients;
ALTER TABLE clients_new RENAME TO clients;
CREATE INDEX "idx_clients_userid" ON clients (user_id);
CREATE UNIQUE INDEX "idx_clients_fcmtoken" ON clients (fcm_token);

View File

@ -26,7 +26,7 @@ type Client struct {
TimestampCreated time.Time
AgentModel string
AgentVersion string
DescriptionName *string
Name *string
}
func (c Client) JSON() ClientJSON {
@ -38,7 +38,7 @@ func (c Client) JSON() ClientJSON {
TimestampCreated: c.TimestampCreated.Format(time.RFC3339Nano),
AgentModel: c.AgentModel,
AgentVersion: c.AgentVersion,
DescriptionName: c.DescriptionName,
Name: c.Name,
}
}
@ -50,7 +50,7 @@ type ClientJSON struct {
TimestampCreated string `json:"timestamp_created"`
AgentModel string `json:"agent_model"`
AgentVersion string `json:"agent_version"`
DescriptionName *string `json:"description_name"`
Name *string `json:"name"`
}
type ClientDB struct {
@ -61,7 +61,7 @@ type ClientDB struct {
TimestampCreated int64 `db:"timestamp_created"`
AgentModel string `db:"agent_model"`
AgentVersion string `db:"agent_version"`
DescriptionName *string `db:"description_name"`
Name *string `db:"name"`
}
func (c ClientDB) Model() Client {
@ -73,7 +73,7 @@ func (c ClientDB) Model() Client {
TimestampCreated: timeFromMilli(c.TimestampCreated),
AgentModel: c.AgentModel,
AgentVersion: c.AgentVersion,
DescriptionName: c.DescriptionName,
Name: c.Name,
}
}

View File

@ -5,7 +5,7 @@ package models
import "gogs.mikescher.com/BlackForestBytes/goext/langext"
import "gogs.mikescher.com/BlackForestBytes/goext/enums"
const ChecksumEnumGenerator = "814434d6d179eec7fb90b380db859daf6051b5d767d83a20633f9ef78d66e857" // GoExtVersion: 0.0.463
const ChecksumEnumGenerator = "08404cad6879118878e2b64db01bb6bf54cda9d51e3d3ff91b239e9a8459fecd" // GoExtVersion: 0.0.463
// ================================ ClientType ================================
//

View File

@ -15,7 +15,7 @@ import "reflect"
import "regexp"
import "strings"
const ChecksumCharsetIDGenerator = "814434d6d179eec7fb90b380db859daf6051b5d767d83a20633f9ef78d66e857" // GoExtVersion: 0.0.463
const ChecksumCharsetIDGenerator = "08404cad6879118878e2b64db01bb6bf54cda9d51e3d3ff91b239e9a8459fecd" // GoExtVersion: 0.0.463
const idlen = 24

View File

@ -1981,6 +1981,64 @@
}
}
},
"/api/v2/users/{uid}/keys/current": {
"get": {
"description": "Can be done with keys of any permission - the returned key does not include its token.",
"tags": [
"API-v2"
],
"summary": "Get the key currently used by this request",
"operationId": "api-tokenkeys-get-current",
"parameters": [
{
"type": "string",
"description": "UserID",
"name": "uid",
"in": "path",
"required": true
},
{
"type": "string",
"description": "TokenKeyID",
"name": "kid",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/models.KeyTokenWithTokenJSON"
}
},
"400": {
"description": "supplied values/parameters cannot be parsed / are invalid",
"schema": {
"$ref": "#/definitions/ginresp.apiError"
}
},
"401": {
"description": "user is not authorized / has missing permissions",
"schema": {
"$ref": "#/definitions/ginresp.apiError"
}
},
"404": {
"description": "message not found",
"schema": {
"$ref": "#/definitions/ginresp.apiError"
}
},
"500": {
"description": "internal server error",
"schema": {
"$ref": "#/definitions/ginresp.apiError"
}
}
}
}
},
"/api/v2/users/{uid}/keys/{kid}": {
"get": {
"description": "The request must be done with an ADMIN key, the returned key does not include its token.",
@ -3039,10 +3097,10 @@
"client_type": {
"$ref": "#/definitions/models.ClientType"
},
"description_name": {
"fcm_token": {
"type": "string"
},
"fcm_token": {
"name": {
"type": "string"
}
}
@ -3084,12 +3142,12 @@
"agent_version": {
"type": "string"
},
"client_name": {
"type": "string"
},
"client_type": {
"$ref": "#/definitions/models.ClientType"
},
"description_name": {
"type": "string"
},
"fcm_token": {
"type": "string"
},
@ -3641,10 +3699,10 @@
"client_id": {
"type": "string"
},
"description_name": {
"fcm_token": {
"type": "string"
},
"fcm_token": {
"name": {
"type": "string"
},
"timestamp_created": {
@ -3736,6 +3794,44 @@
}
}
},
"models.KeyTokenWithTokenJSON": {
"type": "object",
"properties": {
"all_channels": {
"type": "boolean"
},
"channels": {
"type": "array",
"items": {
"type": "string"
}
},
"keytoken_id": {
"type": "string"
},
"messages_sent": {
"type": "integer"
},
"name": {
"type": "string"
},
"owner_user_id": {
"type": "string"
},
"permissions": {
"type": "string"
},
"timestamp_created": {
"type": "string"
},
"timestamp_lastused": {
"type": "string"
},
"token": {
"type": "string"
}
}
},
"models.MessageJSON": {
"type": "object",
"properties": {

View File

@ -129,10 +129,10 @@ definitions:
type: string
client_type:
$ref: '#/definitions/models.ClientType'
description_name:
type: string
fcm_token:
type: string
name:
type: string
required:
- agent_model
- agent_version
@ -163,10 +163,10 @@ definitions:
type: string
agent_version:
type: string
client_name:
type: string
client_type:
$ref: '#/definitions/models.ClientType'
description_name:
type: string
fcm_token:
type: string
no_client:
@ -529,10 +529,10 @@ definitions:
type: string
client_id:
type: string
description_name:
type: string
fcm_token:
type: string
name:
type: string
timestamp_created:
type: string
type:
@ -594,6 +594,31 @@ definitions:
timestamp_lastused:
type: string
type: object
models.KeyTokenWithTokenJSON:
properties:
all_channels:
type: boolean
channels:
items:
type: string
type: array
keytoken_id:
type: string
messages_sent:
type: integer
name:
type: string
owner_user_id:
type: string
permissions:
type: string
timestamp_created:
type: string
timestamp_lastused:
type: string
token:
type: string
type: object
models.MessageJSON:
properties:
channel_id:
@ -2197,6 +2222,46 @@ paths:
summary: Update a key
tags:
- API-v2
/api/v2/users/{uid}/keys/current:
get:
description: Can be done with keys of any permission - the returned key does
not include its token.
operationId: api-tokenkeys-get-current
parameters:
- description: UserID
in: path
name: uid
required: true
type: string
- description: TokenKeyID
in: path
name: kid
required: true
type: string
responses:
"200":
description: OK
schema:
$ref: '#/definitions/models.KeyTokenWithTokenJSON'
"400":
description: supplied values/parameters cannot be parsed / are invalid
schema:
$ref: '#/definitions/ginresp.apiError'
"401":
description: user is not authorized / has missing permissions
schema:
$ref: '#/definitions/ginresp.apiError'
"404":
description: message not found
schema:
$ref: '#/definitions/ginresp.apiError'
"500":
description: internal server error
schema:
$ref: '#/definitions/ginresp.apiError'
summary: Get the key currently used by this request
tags:
- API-v2
/api/v2/users/{uid}/subscriptions:
get:
description: |-

View File

@ -49,6 +49,7 @@ func TestGetClient(t *testing.T) {
tt.AssertEqual(t, "fcm_token", "DUMMY_FCM", c0["fcm_token"])
tt.AssertEqual(t, "client_type", "ANDROID", c0["type"])
tt.AssertEqual(t, "user_id", uid, fmt.Sprintf("%v", c0["user_id"]))
tt.AssertEqual(t, "client_name", nil, c0["name"])
cid := fmt.Sprintf("%v", c0["client_id"])
@ -77,21 +78,54 @@ func TestCreateClient(t *testing.T) {
fmt.Printf("uid := %s\n", uid)
fmt.Printf("admin_key := %s\n", admintok)
tt.RequestAuthPost[gin.H](t, admintok, baseUrl, "/api/v2/users/"+uid+"/clients", gin.H{
type rt3 struct {
Clients []gin.H `json:"clients"`
}
// normal client
{
createdClient := tt.RequestAuthPost[gin.H](t, admintok, baseUrl, "/api/v2/users/"+uid+"/clients", gin.H{
"agent_model": "DUMMY_PHONE_2",
"agent_version": "99X",
"client_type": "IOS",
"fcm_token": "DUMMY_FCM_2",
})
type rt3 struct {
Clients []gin.H `json:"clients"`
tt.AssertEqual(t, "createdClient.agent_model", "DUMMY_PHONE_2", createdClient["agent_model"])
tt.AssertEqual(t, "createdClient.agent_version", "99X", createdClient["agent_version"])
tt.AssertEqual(t, "createdClient.type", "IOS", createdClient["type"])
tt.AssertEqual(t, "createdClient.fcm_token", "DUMMY_FCM_2", createdClient["fcm_token"])
tt.AssertEqual(t, "createdClient.name", nil, createdClient["name"])
}
{
r3 := tt.RequestAuthGet[rt3](t, admintok, baseUrl, "/api/v2/users/"+uid+"/clients")
tt.AssertEqual(t, "len(clients)", 2, len(r3.Clients))
}
// client with name
{
createdClient := tt.RequestAuthPost[gin.H](t, admintok, baseUrl, "/api/v2/users/"+uid+"/clients", gin.H{
"agent_model": "DUMMY_PHONE_2_ASDF",
"agent_version": "XOXO",
"client_type": "LINUX",
"fcm_token": "DUMMY_FCM_2_77777",
"name": "My iPhone 12 Pro Max",
})
tt.AssertEqual(t, "createdClient.agent_model", "DUMMY_PHONE_2_ASDF", createdClient["agent_model"])
tt.AssertEqual(t, "createdClient.agent_version", "XOXO", createdClient["agent_version"])
tt.AssertEqual(t, "createdClient.type", "LINUX", createdClient["type"])
tt.AssertEqual(t, "createdClient.fcm_token", "DUMMY_FCM_2_77777", createdClient["fcm_token"])
tt.AssertEqual(t, "createdClient.name", "My iPhone 12 Pro Max", createdClient["name"])
}
{
r3 := tt.RequestAuthGet[rt3](t, admintok, baseUrl, "/api/v2/users/"+uid+"/clients")
tt.AssertEqual(t, "len(clients)", 3, len(r3.Clients))
}
}
func TestDeleteClient(t *testing.T) {
_, baseUrl, stop := tt.StartSimpleWebserver(t)
defer stop()
@ -256,19 +290,24 @@ func TestUpdateClient(t *testing.T) {
cid2 := fmt.Sprintf("%v", r2["client_id"])
{
type rt3 struct {
Clients []gin.H `json:"clients"`
}
r3 := tt.RequestAuthGet[rt3](t, admintok, baseUrl, "/api/v2/users/"+uid+"/clients")
tt.AssertEqual(t, "len(clients)", 2, len(r3.Clients))
}
{
r4 := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, "/api/v2/users/"+uid+"/clients/"+cid2)
tt.AssertEqual(t, "agent_model", "DUMMY_PHONE_2", r4["agent_model"])
tt.AssertEqual(t, "agent_version", "99X", r4["agent_version"])
tt.AssertEqual(t, "client_type", "IOS", r4["type"])
tt.AssertEqual(t, "fcm_token", "DUMMY_FCM_2", r4["fcm_token"])
}
{
r5 := tt.RequestAuthPatch[gin.H](t, admintok, baseUrl, "/api/v2/users/"+uid+"/clients/"+cid2, gin.H{
"agent_model": "PP_DUMMY_PHONE_2",
"agent_version": "PP_99X",
@ -278,11 +317,54 @@ func TestUpdateClient(t *testing.T) {
tt.AssertEqual(t, "agent_version", "PP_99X", r5["agent_version"])
tt.AssertEqual(t, "client_type", "IOS", r5["type"])
tt.AssertEqual(t, "fcm_token", "PP_DUMMY_FCM_2", r5["fcm_token"])
}
{
r6 := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, "/api/v2/users/"+uid+"/clients/"+cid2)
tt.AssertEqual(t, "agent_model", "PP_DUMMY_PHONE_2", r6["agent_model"])
tt.AssertEqual(t, "agent_version", "PP_99X", r6["agent_version"])
tt.AssertEqual(t, "client_type", "IOS", r6["type"])
tt.AssertEqual(t, "fcm_token", "PP_DUMMY_FCM_2", r6["fcm_token"])
}
{
r7 := tt.RequestAuthPatch[gin.H](t, admintok, baseUrl, "/api/v2/users/"+uid+"/clients/"+cid2, gin.H{
"name": "I am the name",
})
tt.AssertEqual(t, "agent_model", "PP_DUMMY_PHONE_2", r7["agent_model"])
tt.AssertEqual(t, "agent_version", "PP_99X", r7["agent_version"])
tt.AssertEqual(t, "client_type", "IOS", r7["type"])
tt.AssertEqual(t, "fcm_token", "PP_DUMMY_FCM_2", r7["fcm_token"])
tt.AssertEqual(t, "name", "I am the name", r7["name"])
}
{
r8 := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, "/api/v2/users/"+uid+"/clients/"+cid2)
tt.AssertEqual(t, "agent_model", "PP_DUMMY_PHONE_2", r8["agent_model"])
tt.AssertEqual(t, "agent_version", "PP_99X", r8["agent_version"])
tt.AssertEqual(t, "client_type", "IOS", r8["type"])
tt.AssertEqual(t, "fcm_token", "PP_DUMMY_FCM_2", r8["fcm_token"])
tt.AssertEqual(t, "name", "I am the name", r8["name"])
}
{
r9 := tt.RequestAuthPatch[gin.H](t, admintok, baseUrl, "/api/v2/users/"+uid+"/clients/"+cid2, gin.H{
"name": "",
})
tt.AssertEqual(t, "agent_model", "PP_DUMMY_PHONE_2", r9["agent_model"])
tt.AssertEqual(t, "agent_version", "PP_99X", r9["agent_version"])
tt.AssertEqual(t, "client_type", "IOS", r9["type"])
tt.AssertEqual(t, "fcm_token", "PP_DUMMY_FCM_2", r9["fcm_token"])
tt.AssertEqual(t, "name", nil, r9["name"])
}
{
r10 := tt.RequestAuthGet[gin.H](t, admintok, baseUrl, "/api/v2/users/"+uid+"/clients/"+cid2)
tt.AssertEqual(t, "agent_model", "PP_DUMMY_PHONE_2", r10["agent_model"])
tt.AssertEqual(t, "agent_version", "PP_99X", r10["agent_version"])
tt.AssertEqual(t, "client_type", "IOS", r10["type"])
tt.AssertEqual(t, "fcm_token", "PP_DUMMY_FCM_2", r10["fcm_token"])
tt.AssertEqual(t, "name", nil, r10["name"])
}
}