Add KeyToken authorization

This commit is contained in:
2023-04-21 21:45:16 +02:00
parent 16f6ab4861
commit b1bd278f9b
49 changed files with 3109 additions and 1313 deletions

View File

@@ -14,7 +14,6 @@ type Channel struct {
DisplayName string
DescriptionName *string
SubscribeKey string
SendKey string
TimestampCreated time.Time
TimestampLastSent *time.Time
MessagesSent int
@@ -28,7 +27,6 @@ func (c Channel) JSON(includeKey bool) ChannelJSON {
DisplayName: c.DisplayName,
DescriptionName: c.DescriptionName,
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,
@@ -65,7 +63,6 @@ type ChannelJSON struct {
DisplayName string `json:"display_name"`
DescriptionName *string `json:"description_name"`
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_lastsent"`
MessagesSent int `json:"messages_sent"`
@@ -98,8 +95,7 @@ func (c ChannelDB) Model() Channel {
DisplayName: c.DisplayName,
DescriptionName: c.DescriptionName,
SubscribeKey: c.SubscribeKey,
SendKey: c.SendKey,
TimestampCreated: time.UnixMilli(c.TimestampCreated),
TimestampCreated: timeFromMilli(c.TimestampCreated),
TimestampLastSent: timeOptFromMilli(c.TimestampLastSent),
MessagesSent: c.MessagesSent,
}

View File

@@ -7,7 +7,7 @@ import (
"time"
)
type ClientType string
type ClientType string //@enum:type
const (
ClientTypeAndroid ClientType = "ANDROID"
@@ -62,7 +62,7 @@ func (c ClientDB) Model() Client {
UserID: c.UserID,
Type: c.Type,
FCMToken: c.FCMToken,
TimestampCreated: time.UnixMilli(c.TimestampCreated),
TimestampCreated: timeFromMilli(c.TimestampCreated),
AgentModel: c.AgentModel,
AgentVersion: c.AgentVersion,
}

View File

@@ -7,7 +7,7 @@ import (
"time"
)
type DeliveryStatus string
type DeliveryStatus string //@enum:type
const (
DeliveryStatusRetry DeliveryStatus = "RETRY"
@@ -79,7 +79,7 @@ func (d DeliveryDB) Model() Delivery {
MessageID: d.MessageID,
ReceiverUserID: d.ReceiverUserID,
ReceiverClientID: d.ReceiverClientID,
TimestampCreated: time.UnixMilli(d.TimestampCreated),
TimestampCreated: timeFromMilli(d.TimestampCreated),
TimestampFinalized: timeOptFromMilli(d.TimestampFinalized),
Status: d.Status,
RetryCount: d.RetryCount,

View File

@@ -0,0 +1,242 @@
// Code generated by permissions_gen.sh DO NOT EDIT.
package models
import "gogs.mikescher.com/BlackForestBytes/goext/langext"
type Enum interface {
Valid() bool
ValuesAny() []any
ValuesMeta() []EnumMetaValue
VarName() string
}
type StringEnum interface {
Enum
String() string
}
type DescriptionEnum interface {
Enum
Description() string
}
type EnumMetaValue struct {
VarName string `json:"varName"`
Value any `json:"value"`
Description *string `json:"description"`
}
// ================================ ClientType ================================
//
// File: client.go
// StringEnum: true
// DescrEnum: false
//
var __ClientTypeValues = []ClientType{
ClientTypeAndroid,
ClientTypeIOS,
}
var __ClientTypeVarnames = map[ClientType]string{
ClientTypeAndroid: "ClientTypeAndroid",
ClientTypeIOS: "ClientTypeIOS",
}
func (e ClientType) Valid() bool {
return langext.InArray(e, __ClientTypeValues)
}
func (e ClientType) Values() []ClientType {
return __ClientTypeValues
}
func (e ClientType) ValuesAny() []any {
return langext.ArrCastToAny(__ClientTypeValues)
}
func (e ClientType) ValuesMeta() []EnumMetaValue {
return []EnumMetaValue{
EnumMetaValue{VarName: "ClientTypeAndroid", Value: ClientTypeAndroid, Description: nil},
EnumMetaValue{VarName: "ClientTypeIOS", Value: ClientTypeIOS, Description: nil},
}
}
func (e ClientType) String() string {
return string(e)
}
func (e ClientType) VarName() string {
if d, ok := __ClientTypeVarnames[e]; ok {
return d
}
return ""
}
func ParseClientType(vv string) (ClientType, bool) {
for _, ev := range __ClientTypeValues {
if string(ev) == vv {
return ev, true
}
}
return "", false
}
func ClientTypeValues() []ClientType {
return __ClientTypeValues
}
func ClientTypeValuesMeta() []EnumMetaValue {
return []EnumMetaValue{
EnumMetaValue{VarName: "ClientTypeAndroid", Value: ClientTypeAndroid, Description: nil},
EnumMetaValue{VarName: "ClientTypeIOS", Value: ClientTypeIOS, Description: nil},
}
}
// ================================ DeliveryStatus ================================
//
// File: delivery.go
// StringEnum: true
// DescrEnum: false
//
var __DeliveryStatusValues = []DeliveryStatus{
DeliveryStatusRetry,
DeliveryStatusSuccess,
DeliveryStatusFailed,
}
var __DeliveryStatusVarnames = map[DeliveryStatus]string{
DeliveryStatusRetry: "DeliveryStatusRetry",
DeliveryStatusSuccess: "DeliveryStatusSuccess",
DeliveryStatusFailed: "DeliveryStatusFailed",
}
func (e DeliveryStatus) Valid() bool {
return langext.InArray(e, __DeliveryStatusValues)
}
func (e DeliveryStatus) Values() []DeliveryStatus {
return __DeliveryStatusValues
}
func (e DeliveryStatus) ValuesAny() []any {
return langext.ArrCastToAny(__DeliveryStatusValues)
}
func (e DeliveryStatus) ValuesMeta() []EnumMetaValue {
return []EnumMetaValue{
EnumMetaValue{VarName: "DeliveryStatusRetry", Value: DeliveryStatusRetry, Description: nil},
EnumMetaValue{VarName: "DeliveryStatusSuccess", Value: DeliveryStatusSuccess, Description: nil},
EnumMetaValue{VarName: "DeliveryStatusFailed", Value: DeliveryStatusFailed, Description: nil},
}
}
func (e DeliveryStatus) String() string {
return string(e)
}
func (e DeliveryStatus) VarName() string {
if d, ok := __DeliveryStatusVarnames[e]; ok {
return d
}
return ""
}
func ParseDeliveryStatus(vv string) (DeliveryStatus, bool) {
for _, ev := range __DeliveryStatusValues {
if string(ev) == vv {
return ev, true
}
}
return "", false
}
func DeliveryStatusValues() []DeliveryStatus {
return __DeliveryStatusValues
}
func DeliveryStatusValuesMeta() []EnumMetaValue {
return []EnumMetaValue{
EnumMetaValue{VarName: "DeliveryStatusRetry", Value: DeliveryStatusRetry, Description: nil},
EnumMetaValue{VarName: "DeliveryStatusSuccess", Value: DeliveryStatusSuccess, Description: nil},
EnumMetaValue{VarName: "DeliveryStatusFailed", Value: DeliveryStatusFailed, Description: nil},
}
}
// ================================ TokenPerm ================================
//
// File: keytoken.go
// StringEnum: true
// DescrEnum: false
//
var __TokenPermValues = []TokenPerm{
PermAdmin,
PermChannelRead,
PermChannelSend,
PermUserRead,
}
var __TokenPermVarnames = map[TokenPerm]string{
PermAdmin: "PermAdmin",
PermChannelRead: "PermChannelRead",
PermChannelSend: "PermChannelSend",
PermUserRead: "PermUserRead",
}
func (e TokenPerm) Valid() bool {
return langext.InArray(e, __TokenPermValues)
}
func (e TokenPerm) Values() []TokenPerm {
return __TokenPermValues
}
func (e TokenPerm) ValuesAny() []any {
return langext.ArrCastToAny(__TokenPermValues)
}
func (e TokenPerm) ValuesMeta() []EnumMetaValue {
return []EnumMetaValue{
EnumMetaValue{VarName: "PermAdmin", Value: PermAdmin, Description: nil},
EnumMetaValue{VarName: "PermChannelRead", Value: PermChannelRead, Description: nil},
EnumMetaValue{VarName: "PermChannelSend", Value: PermChannelSend, Description: nil},
EnumMetaValue{VarName: "PermUserRead", Value: PermUserRead, Description: nil},
}
}
func (e TokenPerm) String() string {
return string(e)
}
func (e TokenPerm) VarName() string {
if d, ok := __TokenPermVarnames[e]; ok {
return d
}
return ""
}
func ParseTokenPerm(vv string) (TokenPerm, bool) {
for _, ev := range __TokenPermValues {
if string(ev) == vv {
return ev, true
}
}
return "", false
}
func TokenPermValues() []TokenPerm {
return __TokenPermValues
}
func TokenPermValuesMeta() []EnumMetaValue {
return []EnumMetaValue{
EnumMetaValue{VarName: "PermAdmin", Value: PermAdmin, Description: nil},
EnumMetaValue{VarName: "PermChannelRead", Value: PermChannelRead, Description: nil},
EnumMetaValue{VarName: "PermChannelSend", Value: PermChannelSend, Description: nil},
EnumMetaValue{VarName: "PermUserRead", Value: PermUserRead, Description: nil},
}
}

View File

@@ -40,6 +40,7 @@ const (
prefixSubscriptionID = "SUB"
prefixClientID = "CLN"
prefixRequestID = "REQ"
prefixKeyTokenID = "TOK"
)
var (
@@ -50,6 +51,7 @@ var (
regexSubscriptionID = generateRegex(prefixSubscriptionID)
regexClientID = generateRegex(prefixClientID)
regexRequestID = generateRegex(prefixRequestID)
regexKeyTokenID = generateRegex(prefixKeyTokenID)
)
func generateRegex(prefix string) rext.Regex {
@@ -375,3 +377,35 @@ func (id RequestID) CheckString() string {
func (id RequestID) Regex() rext.Regex {
return regexRequestID
}
// ------------------------------------------------------------
type KeyTokenID string
func NewKeyTokenID() KeyTokenID {
return KeyTokenID(generateID(prefixKeyTokenID))
}
func (id KeyTokenID) Valid() error {
return validateID(prefixKeyTokenID, string(id))
}
func (id KeyTokenID) String() string {
return string(id)
}
func (id KeyTokenID) Prefix() string {
return prefixKeyTokenID
}
func (id KeyTokenID) Raw() string {
return getRawData(prefixKeyTokenID, string(id))
}
func (id KeyTokenID) CheckString() string {
return getCheckString(prefixKeyTokenID, string(id))
}
func (id KeyTokenID) Regex() rext.Regex {
return regexKeyTokenID
}

View File

@@ -0,0 +1,160 @@
package models
import (
"github.com/jmoiron/sqlx"
"gogs.mikescher.com/BlackForestBytes/goext/langext"
"gogs.mikescher.com/BlackForestBytes/goext/sq"
"strings"
"time"
)
type TokenPerm string //@enum:type
const (
PermAdmin TokenPerm = "A"
PermChannelRead TokenPerm = "CR"
PermChannelSend TokenPerm = "CS"
PermUserRead TokenPerm = "UR"
)
type TokenPermissionList []TokenPerm
func (e TokenPermissionList) Any(p ...TokenPerm) bool {
for _, v1 := range e {
for _, v2 := range p {
if v1 == v2 {
return true
}
}
}
return false
}
func (e TokenPermissionList) String() string {
return strings.Join(langext.ArrMap(e, func(v TokenPerm) string { return string(v) }), ";")
}
func ParseTokenPermissionList(input string) TokenPermissionList {
r := make([]TokenPerm, 0, len(input))
for _, v := range strings.Split(input, ";") {
if vv, ok := ParseTokenPerm(v); ok {
r = append(r, vv)
}
}
return r
}
type KeyToken struct {
KeyTokenID KeyTokenID
Name string
TimestampCreated time.Time
TimestampLastUsed *time.Time
OwnerUserID UserID
AllChannels bool
Channels []ChannelID // can also be owned by other user (needs active subscription)
Token string
Permissions TokenPermissionList
MessagesSent int
}
func (k KeyToken) IsUserRead(uid UserID) bool {
return k.OwnerUserID == uid && k.Permissions.Any(PermAdmin, PermUserRead)
}
func (k KeyToken) IsAllMessagesRead(uid UserID) bool {
return k.OwnerUserID == uid && k.AllChannels == true && k.Permissions.Any(PermAdmin, PermChannelRead)
}
func (k KeyToken) IsChannelMessagesRead(cid ChannelID) bool {
return (k.AllChannels == true || langext.InArray(cid, k.Channels)) && k.Permissions.Any(PermAdmin, PermChannelRead)
}
func (k KeyToken) IsAdmin(uid UserID) bool {
return k.OwnerUserID == uid && k.Permissions.Any(PermAdmin)
}
func (k KeyToken) IsChannelMessagesSend(c Channel) bool {
return (k.AllChannels == true || langext.InArray(c.ChannelID, k.Channels)) && k.OwnerUserID == c.OwnerUserID && k.Permissions.Any(PermAdmin, PermChannelSend)
}
func (k KeyToken) JSON() KeyTokenJSON {
return KeyTokenJSON{
KeyTokenID: k.KeyTokenID,
Name: k.Name,
TimestampCreated: k.TimestampCreated,
TimestampLastUsed: k.TimestampLastUsed,
OwnerUserID: k.OwnerUserID,
AllChannels: k.AllChannels,
Channels: k.Channels,
Permissions: k.Permissions.String(),
MessagesSent: k.MessagesSent,
}
}
type KeyTokenJSON struct {
KeyTokenID KeyTokenID `json:"keytoken_id"`
Name string `json:"name"`
TimestampCreated time.Time `json:"timestamp_created"`
TimestampLastUsed *time.Time `json:"timestamp_lastused"`
OwnerUserID UserID `json:"owner_user_id"`
AllChannels bool `json:"all_channels"`
Channels []ChannelID `json:"channels"`
Permissions string `json:"permissions"`
MessagesSent int `json:"messages_sent"`
}
type KeyTokenWithTokenJSON struct {
KeyTokenJSON
Token string `json:"token"`
}
func (j KeyTokenJSON) WithToken(tok string) any {
return KeyTokenWithTokenJSON{
KeyTokenJSON: j,
Token: tok,
}
}
type KeyTokenDB struct {
KeyTokenID KeyTokenID `db:"keytoken_id"`
Name string `db:"name"`
TimestampCreated int64 `db:"timestamp_created"`
TimestampLastUsed *int64 `db:"timestamp_lastused"`
OwnerUserID UserID `db:"owner_user_id"`
AllChannels bool `db:"all_channels"`
Channels string `db:"channels"`
Token string `db:"token"`
Permissions string `db:"permissions"`
MessagesSent int `db:"messages_sent"`
}
func (k KeyTokenDB) Model() KeyToken {
return KeyToken{
KeyTokenID: k.KeyTokenID,
Name: k.Name,
TimestampCreated: timeFromMilli(k.TimestampCreated),
TimestampLastUsed: timeOptFromMilli(k.TimestampLastUsed),
OwnerUserID: k.OwnerUserID,
AllChannels: k.AllChannels,
Channels: langext.ArrMap(strings.Split(k.Channels, ";"), func(v string) ChannelID { return ChannelID(v) }),
Token: k.Token,
Permissions: ParseTokenPermissionList(k.Permissions),
MessagesSent: k.MessagesSent,
}
}
func DecodeKeyToken(r *sqlx.Rows) (KeyToken, error) {
data, err := sq.ScanSingle[KeyTokenDB](r, sq.SModeFast, sq.Safe, true)
if err != nil {
return KeyToken{}, err
}
return data.Model(), nil
}
func DecodeKeyTokens(r *sqlx.Rows) ([]KeyToken, error) {
data, err := sq.ScanAll[KeyTokenDB](r, sq.SModeFast, sq.Safe, true)
if err != nil {
return nil, err
}
return langext.ArrMap(data, func(v KeyTokenDB) KeyToken { return v.Model() }), nil
}

View File

@@ -135,7 +135,7 @@ func (m MessageDB) Model() Message {
ChannelID: m.ChannelID,
SenderName: m.SenderName,
SenderIP: m.SenderIP,
TimestampReal: time.UnixMilli(m.TimestampReal),
TimestampReal: timeFromMilli(m.TimestampReal),
TimestampClient: timeOptFromMilli(m.TimestampClient),
Title: m.Title,
Content: m.Content,

View File

@@ -1,22 +1,11 @@
package models
type PermKeyType string
const (
PermKeyTypeNone PermKeyType = "NONE" // (nothing)
PermKeyTypeUserSend PermKeyType = "USER_SEND" // send-messages
PermKeyTypeUserRead PermKeyType = "USER_READ" // send-messages, list-messages, read-user
PermKeyTypeUserAdmin PermKeyType = "USER_ADMIN" // send-messages, list-messages, read-user, delete-messages, update-user
)
type PermissionSet struct {
UserID *UserID
KeyType PermKeyType
Token *KeyToken // KeyToken.Permissions
}
func NewEmptyPermissions() PermissionSet {
return PermissionSet{
UserID: nil,
KeyType: PermKeyTypeNone,
Token: nil,
}
}

View File

@@ -18,6 +18,7 @@ type RequestLog struct {
RequestBodySize int64
RequestContentType string
RemoteIP string
TokenID *KeyTokenID
UserID *UserID
Permissions *string
ResponseStatuscode *int64
@@ -44,6 +45,7 @@ func (c RequestLog) JSON() RequestLogJSON {
RequestBodySize: c.RequestBodySize,
RequestContentType: c.RequestContentType,
RemoteIP: c.RemoteIP,
TokenID: c.TokenID,
UserID: c.UserID,
Permissions: c.Permissions,
ResponseStatuscode: c.ResponseStatuscode,
@@ -71,6 +73,7 @@ func (c RequestLog) DB() RequestLogDB {
RequestBodySize: c.RequestBodySize,
RequestContentType: c.RequestContentType,
RemoteIP: c.RemoteIP,
TokenID: c.TokenID,
UserID: c.UserID,
Permissions: c.Permissions,
ResponseStatuscode: c.ResponseStatuscode,
@@ -88,53 +91,55 @@ func (c RequestLog) DB() RequestLogDB {
}
type RequestLogJSON struct {
RequestID RequestID `json:"requestLog_id"`
Method string `json:"method"`
URI string `json:"uri"`
UserAgent *string `json:"user_agent"`
Authentication *string `json:"authentication"`
RequestBody *string `json:"request_body"`
RequestBodySize int64 `json:"request_body_size"`
RequestContentType string `json:"request_content_type"`
RemoteIP string `json:"remote_ip"`
UserID *UserID `json:"userid"`
Permissions *string `json:"permissions"`
ResponseStatuscode *int64 `json:"response_statuscode"`
ResponseBodySize *int64 `json:"response_body_size"`
ResponseBody *string `json:"response_body"`
ResponseContentType string `json:"response_content_type"`
RetryCount int64 `json:"retry_count"`
Panicked bool `json:"panicked"`
PanicStr *string `json:"panic_str"`
ProcessingTime float64 `json:"processing_time"`
TimestampCreated string `json:"timestamp_created"`
TimestampStart string `json:"timestamp_start"`
TimestampFinish string `json:"timestamp_finish"`
RequestID RequestID `json:"requestLog_id"`
Method string `json:"method"`
URI string `json:"uri"`
UserAgent *string `json:"user_agent"`
Authentication *string `json:"authentication"`
RequestBody *string `json:"request_body"`
RequestBodySize int64 `json:"request_body_size"`
RequestContentType string `json:"request_content_type"`
RemoteIP string `json:"remote_ip"`
TokenID *KeyTokenID `json:"token_id"`
UserID *UserID `json:"userid"`
Permissions *string `json:"permissions"`
ResponseStatuscode *int64 `json:"response_statuscode"`
ResponseBodySize *int64 `json:"response_body_size"`
ResponseBody *string `json:"response_body"`
ResponseContentType string `json:"response_content_type"`
RetryCount int64 `json:"retry_count"`
Panicked bool `json:"panicked"`
PanicStr *string `json:"panic_str"`
ProcessingTime float64 `json:"processing_time"`
TimestampCreated string `json:"timestamp_created"`
TimestampStart string `json:"timestamp_start"`
TimestampFinish string `json:"timestamp_finish"`
}
type RequestLogDB struct {
RequestID RequestID `db:"requestLog_id"`
Method string `db:"method"`
URI string `db:"uri"`
UserAgent *string `db:"user_agent"`
Authentication *string `db:"authentication"`
RequestBody *string `db:"request_body"`
RequestBodySize int64 `db:"request_body_size"`
RequestContentType string `db:"request_content_type"`
RemoteIP string `db:"remote_ip"`
UserID *UserID `db:"userid"`
Permissions *string `db:"permissions"`
ResponseStatuscode *int64 `db:"response_statuscode"`
ResponseBodySize *int64 `db:"response_body_size"`
ResponseBody *string `db:"response_body"`
ResponseContentType string `db:"request_content_type"`
RetryCount int64 `db:"retry_count"`
Panicked int64 `db:"panicked"`
PanicStr *string `db:"panic_str"`
ProcessingTime int64 `db:"processing_time"`
TimestampCreated int64 `db:"timestamp_created"`
TimestampStart int64 `db:"timestamp_start"`
TimestampFinish int64 `db:"timestamp_finish"`
RequestID RequestID `db:"requestLog_id"`
Method string `db:"method"`
URI string `db:"uri"`
UserAgent *string `db:"user_agent"`
Authentication *string `db:"authentication"`
RequestBody *string `db:"request_body"`
RequestBodySize int64 `db:"request_body_size"`
RequestContentType string `db:"request_content_type"`
RemoteIP string `db:"remote_ip"`
TokenID *KeyTokenID `db:"token_id"`
UserID *UserID `db:"userid"`
Permissions *string `db:"permissions"`
ResponseStatuscode *int64 `db:"response_statuscode"`
ResponseBodySize *int64 `db:"response_body_size"`
ResponseBody *string `db:"response_body"`
ResponseContentType string `db:"request_content_type"`
RetryCount int64 `db:"retry_count"`
Panicked int64 `db:"panicked"`
PanicStr *string `db:"panic_str"`
ProcessingTime int64 `db:"processing_time"`
TimestampCreated int64 `db:"timestamp_created"`
TimestampStart int64 `db:"timestamp_start"`
TimestampFinish int64 `db:"timestamp_finish"`
}
func (c RequestLogDB) Model() RequestLog {
@@ -158,9 +163,9 @@ func (c RequestLogDB) Model() RequestLog {
Panicked: c.Panicked != 0,
PanicStr: c.PanicStr,
ProcessingTime: timeext.FromMilliseconds(c.ProcessingTime),
TimestampCreated: time.UnixMilli(c.TimestampCreated),
TimestampStart: time.UnixMilli(c.TimestampStart),
TimestampFinish: time.UnixMilli(c.TimestampFinish),
TimestampCreated: timeFromMilli(c.TimestampCreated),
TimestampStart: timeFromMilli(c.TimestampStart),
TimestampFinish: timeFromMilli(c.TimestampFinish),
}
}

View File

@@ -7,6 +7,13 @@ import (
"time"
)
// [!] subscriptions are read-access to channels,
//
// The set of subscriptions specifies which messages the ListMessages() API call returns
// also single messages/channels that are subscribed can be queries
//
// (use keytokens for write-access)
type Subscription struct {
SubscriptionID SubscriptionID
SubscriberUserID UserID
@@ -56,7 +63,7 @@ func (s SubscriptionDB) Model() Subscription {
ChannelOwnerUserID: s.ChannelOwnerUserID,
ChannelID: s.ChannelID,
ChannelInternalName: s.ChannelInternalName,
TimestampCreated: time.UnixMilli(s.TimestampCreated),
TimestampCreated: timeFromMilli(s.TimestampCreated),
Confirmed: s.Confirmed != 0,
}
}

View File

@@ -11,9 +11,6 @@ import (
type User struct {
UserID UserID
Username *string
SendKey string
ReadKey string
AdminKey string
TimestampCreated time.Time
TimestampLastRead *time.Time
TimestampLastSent *time.Time
@@ -28,9 +25,6 @@ func (u User) JSON() UserJSON {
return UserJSON{
UserID: u.UserID,
Username: u.Username,
ReadKey: u.ReadKey,
SendKey: u.SendKey,
AdminKey: u.AdminKey,
TimestampCreated: u.TimestampCreated.Format(time.RFC3339Nano),
TimestampLastRead: timeOptFmt(u.TimestampLastRead, time.RFC3339Nano),
TimestampLastSent: timeOptFmt(u.TimestampLastSent, time.RFC3339Nano),
@@ -43,10 +37,13 @@ func (u User) JSON() UserJSON {
}
}
func (u User) JSONWithClients(clients []Client) UserJSONWithClients {
return UserJSONWithClients{
func (u User) JSONWithClients(clients []Client, ak string, sk string, rk string) UserJSONWithClientsAndKeys {
return UserJSONWithClientsAndKeys{
UserJSON: u.JSON(),
Clients: langext.ArrMap(clients, func(v Client) ClientJSON { return v.JSON() }),
SendKey: sk,
ReadKey: rk,
AdminKey: ak,
}
}
@@ -114,9 +111,6 @@ func (u User) MaxTimestampDiffHours() int {
type UserJSON struct {
UserID UserID `json:"user_id"`
Username *string `json:"username"`
ReadKey string `json:"read_key"`
SendKey string `json:"send_key"`
AdminKey string `json:"admin_key"`
TimestampCreated string `json:"timestamp_created"`
TimestampLastRead *string `json:"timestamp_lastread"`
TimestampLastSent *string `json:"timestamp_lastsent"`
@@ -128,17 +122,17 @@ type UserJSON struct {
DefaultChannel string `json:"default_channel"`
}
type UserJSONWithClients struct {
type UserJSONWithClientsAndKeys struct {
UserJSON
Clients []ClientJSON `json:"clients"`
Clients []ClientJSON `json:"clients"`
SendKey string `json:"send_key"`
ReadKey string `json:"read_key"`
AdminKey string `json:"admin_key"`
}
type UserDB struct {
UserID UserID `db:"user_id"`
Username *string `db:"username"`
SendKey string `db:"send_key"`
ReadKey string `db:"read_key"`
AdminKey string `db:"admin_key"`
TimestampCreated int64 `db:"timestamp_created"`
TimestampLastRead *int64 `db:"timestamp_lastread"`
TimestampLastSent *int64 `db:"timestamp_lastsent"`
@@ -153,10 +147,7 @@ func (u UserDB) Model() User {
return User{
UserID: u.UserID,
Username: u.Username,
SendKey: u.SendKey,
ReadKey: u.ReadKey,
AdminKey: u.AdminKey,
TimestampCreated: time.UnixMilli(u.TimestampCreated),
TimestampCreated: timeFromMilli(u.TimestampCreated),
TimestampLastRead: timeOptFromMilli(u.TimestampLastRead),
TimestampLastSent: timeOptFromMilli(u.TimestampLastSent),
MessagesSent: u.MessagesSent,

View File

@@ -5,6 +5,8 @@ import (
"time"
)
//go:generate go run ../_gen/enum-generate.go -- enums_gen.go
func timeOptFmt(t *time.Time, fmt string) *string {
if t == nil {
return nil
@@ -19,3 +21,7 @@ func timeOptFromMilli(millis *int64) *time.Time {
}
return langext.Ptr(time.UnixMilli(*millis))
}
func timeFromMilli(millis int64) time.Time {
return time.UnixMilli(millis)
}