adding endpoint to push contact notifications

This commit is contained in:
Roland Osborne 2022-11-13 22:18:54 -08:00
parent 887fd65c75
commit 44801ae6c3
13 changed files with 125 additions and 67 deletions

View File

@ -1,9 +1,7 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function setAccountAccess(server, token, notifications) {
let app = { Name: "indicom", Description: "decentralized communication" }
let types = encodeURIComponent(JSON.stringify(notifications));
let access = await fetchWithTimeout(`https://${server}/account/access?token=${token}&appName=${appName}&appVersion=${appVersion}&platform=${platform}&deviceToken=${deviceToken}&notifications=${types}`, { method: 'PUT', body: JSON.stringify(app) })
export async function setAccountAccess(server, token, appName, appVersion, platofrm, notifications) {
let access = await fetchWithTimeout(`https://${server}/account/access?token=${token}&appName=${appName}&appVersion=${appVersion}&platform=${platform}&deviceToken=${deviceToken}`, { method: 'PUT', body: JSON.stringify(notifications) })
checkResponse(access)
return await access.json()
}

View File

@ -4,9 +4,7 @@ import base64 from 'react-native-base64'
export async function setLogin(username, server, password, appName, appVersion, platform, deviceToken, notifications) {
let headers = new Headers()
headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));
let types = encodeURIComponent(JSON.stringify(notifications));
let app = { Name: "topics", Description: "decentralized communication" }
let login = await fetchWithTimeout(`https://${server}/account/apps?appName=${appName}&appVersion=${appVersion}&platform=${platform}&deviceToken=${deviceToken}&notifications=${types}`, { method: 'POST', body: JSON.stringify(app), headers: headers })
let login = await fetchWithTimeout(`https://${server}/account/apps?appName=${appName}&appVersion=${appVersion}&platform=${platform}&deviceToken=${deviceToken}`, { method: 'POST', body: JSON.stringify(notifications), headers: headers })
checkResponse(login)
return await login.json()
}

View File

@ -71,23 +71,29 @@ export function useAppContext() {
clearWebsocket();
}
const notifications = [
{ event: 'contact.statusChange', messageTitle: 'Contact Update' },
{ event: 'channel.addChannel.superbasic', messageTitle: 'New Topic' },
{ event: 'contact.addChannelTopic.superbasictopic', messageTitle: 'New Topic Message' },
];
const actions = {
available: getAvailable,
username: getUsername,
create: async (server, username, password, token) => {
await addAccount(server, username, password, token);
const access = await setLogin(username, server, password, getApplicatioName(), getVersion(), getDeviceId(), state.deviceToken, ['contact', 'channel'])
const access = await setLogin(username, server, password, getApplicatioName(), getVersion(), getDeviceId(), state.deviceToken, notifications)
await store.actions.setSession({ ...access, server});
await setSession({ ...access, server });
},
access: async (server, token) => {
const access = await setAccountAccess(server, token, getApplicationName(), getVersion(), getDeviceId(), state.deviceToken, ['contact', 'channel']);
const access = await setAccountAccess(server, token, getApplicationName(), getVersion(), getDeviceId(), state.deviceToken, notifications);
await store.actions.setSession({ ...access, server});
await setSession({ ...access, server });
},
login: async (username, password) => {
const acc = username.split('@');
const access = await setLogin(acc[0], acc[1], password, getApplicationName(), getVersion(), getDeviceId(), state.deviceToken, ['contact', 'channel'])
const access = await setLogin(acc[0], acc[1], password, getApplicationName(), getVersion(), getDeviceId(), state.deviceToken, notifications)
if (access.pushSupported) {
messaging().requestPermission().then(status => {})
}

View File

@ -2058,6 +2058,34 @@ paths:
schema:
type: integer
format: int64
/contact/notification:
post:
tags:
- contact
description: Inform contact of a push notification event
operationId: set-push-event
paramters:
- name: contact
in: query
description: contact token
required: true
schema:
type: string
responses:
'200':
description: event set
'401':
description: not authorized
'410':
description: account disabled
'500':
description: internal server error
requestBody:
content:
application/json:
schema:
type: string
/attribute/articles:
get:

View File

@ -3,11 +3,9 @@ package databag
import (
"databag/internal/store"
"encoding/hex"
"encoding/json"
"github.com/theckman/go-securerandom"
"gorm.io/gorm"
"net/http"
"errors"
)
//AddAccountApp with access token, attach an app to an account generating agent token
@ -24,17 +22,10 @@ func AddAccountApp(w http.ResponseWriter, r *http.Request) {
appVersion := r.FormValue("appVersion")
platform := r.FormValue("platform")
deviceToken := r.FormValue("deviceToken")
var notifications []string
if r.FormValue("notifications") != "" {
if err := json.Unmarshal([]byte(r.FormValue("notifications")), &notifications); err != nil {
ErrResponse(w, http.StatusBadRequest, errors.New("invalid notification types"));
return;
}
}
// parse app data
var appData AppData
if err := ParseRequest(r, w, &appData); err != nil {
// parse requested notifications
var notifications []Notification
if err := ParseRequest(r, w, &notifications); err != nil {
ErrResponse(w, http.StatusBadRequest, err)
return
}
@ -70,10 +61,12 @@ func AddAccountApp(w http.ResponseWriter, r *http.Request) {
login.Created = session.Created
for _, notification := range notifications {
eventType := &store.EventType{}
eventType.SessionID = session.ID
eventType.Name = notification
if res := tx.Save(eventType).Error; res != nil {
pushEvent := &store.PushEvent{}
pushEvent.SessionID = session.ID
pushEvent.Event = notification.Event
pushEvent.MessageTitle = notification.MessageTitle
pushEvent.MessageBody = notification.MessageBody
if res := tx.Save(pushEvent).Error; res != nil {
return res
}
}

View File

@ -3,7 +3,6 @@ package databag
import (
"databag/internal/store"
"encoding/hex"
"encoding/json"
"errors"
"time"
"github.com/theckman/go-securerandom"
@ -31,20 +30,13 @@ func SetAccountAccess(w http.ResponseWriter, r *http.Request) {
appVersion := r.FormValue("appVersion")
platform := r.FormValue("platform")
deviceToken := r.FormValue("deviceToken")
var notifications []string
if r.FormValue("notifications") != "" {
if err := json.Unmarshal([]byte(r.FormValue("notifications")), &notifications); err != nil {
ErrResponse(w, http.StatusBadRequest, errors.New("invalid notification types"));
return;
}
}
// parse app data
var appData AppData
if err := ParseRequest(r, w, &appData); err != nil {
ErrResponse(w, http.StatusBadRequest, err)
return
}
// parse requested notifications
var notifications []Notification
if err := ParseRequest(r, w, &notifications); err != nil {
ErrResponse(w, http.StatusBadRequest, err)
return
}
// gernate app token
data, err := securerandom.Bytes(APPTokenSize)
@ -70,10 +62,12 @@ func SetAccountAccess(w http.ResponseWriter, r *http.Request) {
return res
}
for _, notification := range notifications {
eventType := &store.EventType{}
eventType.SessionID = session.ID
eventType.Name = notification
if res := tx.Save(eventType).Error; res != nil {
pushEvent := &store.PushEvent{}
pushEvent.SessionID = session.ID
pushEvent.Event = notification.Event
pushEvent.MessageTitle = notification.MessageTitle
pushEvent.MessageBody = notification.MessageBody
if res := tx.Save(pushEvent).Error; res != nil {
return res
}
}

View File

@ -0,0 +1,42 @@
package databag
import (
"databag/internal/store"
"net/http"
)
type push struct {
PushToken string
MessageTitle string
MessageBody string
}
//AddPushEvent notify account of event to push notify
func SetPushEvent(w http.ResponseWriter, r *http.Request) {
card, code, err := ParamContactToken(r, false)
if err != nil {
ErrResponse(w, code, err)
return
}
var event string
if err := ParseRequest(r, w, &event); err != nil {
ErrResponse(w, http.StatusBadRequest, err)
return
}
messages := []push{}
if err := store.DB.Model(&store.Session{}).Select("sessions.push_token, push_events.message_title, push_events.message_body").Joins("left join push_events on push_events.session_id = session.id").Where("sessions.account_id = ? AND session.push_enabled = ?", card.Account.ID, true).Scan(messages).Error; err != nil {
ErrResponse(w, http.StatusInternalServerError, err)
return
}
// send push notification for each
for _, message := range messages {
PrintMsg(message);
}
WriteResponse(w, nil)
}

View File

@ -39,17 +39,13 @@ type Announce struct {
AppToken string `json:"appToken"`
}
//AppData describes app connected to account
type AppData struct {
Name string `json:"name,omitempty"`
//Notification describes type of notifications to receive
type Notification struct {
Event string `json:"event,omitempty"`
Description string `json:"description,omitempty"`
MessageTitle string `json:"messageTitle,omitempty"`
URL string `json:"url,omitempty"`
Image string `json:"image,omitempty"`
Attached int64 `json:"attached"`
MessageBody string `json:"messageBoday,omitempty"`
}
//Article slot for account data shared by group list

View File

@ -524,6 +524,13 @@ var endpoints = routes{
SetViewRevision,
},
route{
"SetPushEvent",
strings.ToUpper("Post"),
"/contact/notification",
SetPushEvent,
},
route{
"AddChannel",
strings.ToUpper("Post"),

View File

@ -7,7 +7,7 @@ func AutoMigrate(db *gorm.DB) {
db.AutoMigrate(&Config{});
db.AutoMigrate(&App{});
db.AutoMigrate(&Session{});
db.AutoMigrate(&EventType{});
db.AutoMigrate(&PushEvent{});
db.AutoMigrate(&Account{});
db.AutoMigrate(&AccountToken{});
db.AutoMigrate(&GroupSlot{});
@ -108,13 +108,15 @@ type Session struct {
Created int64 `gorm:"autoCreateTime"`
Account Account `gorm:"references:GUID"`
Token string `gorm:"not null;index:sessguid,unique"`
EventTypes []EventType
PushEvents []PushEvent
}
type EventType struct {
type PushEvent struct {
ID uint `gorm:"primaryKey;not null;unique;autoIncrement"`
SessionID uint `gorm:"not null;index:sessiontype"`
Name string
Event string
MessageTitle string
MessageBody string
Session *Session
}

View File

@ -614,11 +614,6 @@ func addTestAccount(username string) (guid string, token string, err error) {
var w *httptest.ResponseRecorder
var access LoginAccess
app := AppData{
Name: "Appy",
Description: "A test app",
URL: "http://app.coredb.org",
}
var claim Claim
var msg DataMessage
var profile Profile
@ -646,7 +641,8 @@ func addTestAccount(username string) (guid string, token string, err error) {
guid = profile.GUID
// acquire new token for attaching app
if r, w, err = NewRequest("POST", "/account/apps", &app); err != nil {
notifications := []Notification{}
if r, w, err = NewRequest("POST", "/account/apps", &notifications); err != nil {
return
}
SetBasicAuth(r, login)

View File

@ -1,8 +1,7 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function setAccountAccess(token, appName, appVersion, platform) {
let app = { Name: "indicom", Description: "decentralized communication" }
let access = await fetchWithTimeout(`/account/access?token=${token}&appName=${appName}&appVersion=${appVersion}&platform=${platform}`, { method: 'PUT', body: JSON.stringify(app) })
let access = await fetchWithTimeout(`/account/access?token=${token}&appName=${appName}&appVersion=${appVersion}&platform=${platform}`, { method: 'PUT', body: JSON.stringify([]) })
checkResponse(access)
return await access.json()
}

View File

@ -5,8 +5,7 @@ export async function setLogin(username, password, appName, appVersion, userAgen
const platform = encodeURIComponent(userAgent);
let headers = new Headers()
headers.append('Authorization', 'Basic ' + base64.encode(username + ":" + password));
let app = { Name: "indicom", Description: "decentralized communication" }
let login = await fetchWithTimeout(`/account/apps?appName=${appName}&appVersion=${appVersion}&platform=${platform}`, { method: 'POST', body: JSON.stringify(app), headers: headers })
let login = await fetchWithTimeout(`/account/apps?appName=${appName}&appVersion=${appVersion}&platform=${platform}`, { method: 'POST', body: JSON.stringify([]), headers: headers })
checkResponse(login)
return await login.json()
}