Add KeyToken authorization
This commit is contained in:
@@ -14,6 +14,7 @@ import (
|
||||
)
|
||||
|
||||
type AppContext struct {
|
||||
app *Application
|
||||
inner context.Context
|
||||
cancelFunc context.CancelFunc
|
||||
cancelled bool
|
||||
@@ -22,8 +23,9 @@ type AppContext struct {
|
||||
ginContext *gin.Context
|
||||
}
|
||||
|
||||
func CreateAppContext(g *gin.Context, innerCtx context.Context, cancelFn context.CancelFunc) *AppContext {
|
||||
func CreateAppContext(app *Application, g *gin.Context, innerCtx context.Context, cancelFn context.CancelFunc) *AppContext {
|
||||
return &AppContext{
|
||||
app: app,
|
||||
inner: innerCtx,
|
||||
cancelFunc: cancelFn,
|
||||
cancelled: false,
|
||||
|
@@ -248,7 +248,7 @@ func (app *Application) StartRequest(g *gin.Context, uri any, query any, body an
|
||||
}
|
||||
|
||||
ictx, cancel := context.WithTimeout(context.Background(), app.Config.RequestTimeout)
|
||||
actx := CreateAppContext(g, ictx, cancel)
|
||||
actx := CreateAppContext(app, g, ictx, cancel)
|
||||
|
||||
authheader := g.GetHeader("Authorization")
|
||||
|
||||
@@ -280,19 +280,19 @@ func (app *Application) getPermissions(ctx *AppContext, hdr string) (models.Perm
|
||||
|
||||
key := strings.TrimSpace(hdr[4:])
|
||||
|
||||
user, err := app.Database.Primary.GetUserByKey(ctx, key)
|
||||
tok, err := app.Database.Primary.GetKeyTokenByToken(ctx, key)
|
||||
if err != nil {
|
||||
return models.PermissionSet{}, err
|
||||
}
|
||||
|
||||
if user != nil && user.SendKey == key {
|
||||
return models.PermissionSet{UserID: langext.Ptr(user.UserID), KeyType: models.PermKeyTypeUserSend}, nil
|
||||
}
|
||||
if user != nil && user.ReadKey == key {
|
||||
return models.PermissionSet{UserID: langext.Ptr(user.UserID), KeyType: models.PermKeyTypeUserRead}, nil
|
||||
}
|
||||
if user != nil && user.AdminKey == key {
|
||||
return models.PermissionSet{UserID: langext.Ptr(user.UserID), KeyType: models.PermKeyTypeUserAdmin}, nil
|
||||
if tok != nil {
|
||||
|
||||
err = app.Database.Primary.UpdateKeyTokenLastUsed(ctx, tok.KeyTokenID)
|
||||
if err != nil {
|
||||
return models.PermissionSet{}, err
|
||||
}
|
||||
|
||||
return models.PermissionSet{Token: tok}, nil
|
||||
}
|
||||
|
||||
return models.NewEmptyPermissions(), nil
|
||||
@@ -309,9 +309,8 @@ func (app *Application) GetOrCreateChannel(ctx *AppContext, userid models.UserID
|
||||
}
|
||||
|
||||
subscribeKey := app.GenerateRandomAuthKey()
|
||||
sendKey := app.GenerateRandomAuthKey()
|
||||
|
||||
newChan, err := app.Database.Primary.CreateChannel(ctx, userid, displayChanName, intChanName, subscribeKey, sendKey)
|
||||
newChan, err := app.Database.Primary.CreateChannel(ctx, userid, displayChanName, intChanName, subscribeKey)
|
||||
if err != nil {
|
||||
return models.Channel{}, err
|
||||
}
|
||||
|
@@ -4,94 +4,116 @@ import (
|
||||
"blackforestbytes.com/simplecloudnotifier/api/apierr"
|
||||
"blackforestbytes.com/simplecloudnotifier/api/ginresp"
|
||||
"blackforestbytes.com/simplecloudnotifier/models"
|
||||
"database/sql"
|
||||
"gogs.mikescher.com/BlackForestBytes/goext/langext"
|
||||
)
|
||||
|
||||
func (ac *AppContext) CheckPermissionUserRead(userid models.UserID) *ginresp.HTTPResponse {
|
||||
p := ac.permissions
|
||||
if p.UserID != nil && *p.UserID == userid && p.KeyType == models.PermKeyTypeUserRead {
|
||||
return nil
|
||||
}
|
||||
if p.UserID != nil && *p.UserID == userid && p.KeyType == models.PermKeyTypeUserAdmin {
|
||||
if p.Token != nil && p.Token.IsUserRead(userid) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return langext.Ptr(ginresp.APIError(ac.ginContext, 401, apierr.USER_AUTH_FAILED, "You are not authorized for this action", nil))
|
||||
}
|
||||
|
||||
func (ac *AppContext) CheckPermissionRead() *ginresp.HTTPResponse {
|
||||
func (ac *AppContext) CheckPermissionSelfAllMessagesRead() *ginresp.HTTPResponse {
|
||||
p := ac.permissions
|
||||
if p.UserID != nil && p.KeyType == models.PermKeyTypeUserRead {
|
||||
if p.Token != nil && p.Token.IsAllMessagesRead(p.Token.OwnerUserID) {
|
||||
return nil
|
||||
}
|
||||
if p.UserID != nil && p.KeyType == models.PermKeyTypeUserAdmin {
|
||||
|
||||
return langext.Ptr(ginresp.APIError(ac.ginContext, 401, apierr.USER_AUTH_FAILED, "You are not authorized for this action", nil))
|
||||
}
|
||||
|
||||
func (ac *AppContext) CheckPermissionAllMessagesRead(userid models.UserID) *ginresp.HTTPResponse {
|
||||
p := ac.permissions
|
||||
if p.Token != nil && p.Token.IsAllMessagesRead(userid) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return langext.Ptr(ginresp.APIError(ac.ginContext, 401, apierr.USER_AUTH_FAILED, "You are not authorized for this action", nil))
|
||||
}
|
||||
|
||||
func (ac *AppContext) CheckPermissionChanMessagesRead(channel models.Channel) *ginresp.HTTPResponse {
|
||||
p := ac.permissions
|
||||
if p.Token != nil && p.Token.IsChannelMessagesRead(channel.ChannelID) {
|
||||
|
||||
if channel.OwnerUserID == p.Token.OwnerUserID {
|
||||
return nil // owned channel
|
||||
} else {
|
||||
sub, err := ac.app.Database.Primary.GetSubscriptionBySubscriber(ac, p.Token.OwnerUserID, channel.ChannelID)
|
||||
if err == sql.ErrNoRows {
|
||||
return langext.Ptr(ginresp.APIError(ac.ginContext, 401, apierr.USER_AUTH_FAILED, "You are not authorized for this action", nil))
|
||||
}
|
||||
if err != nil {
|
||||
return langext.Ptr(ginresp.APIError(ac.ginContext, 500, apierr.DATABASE_ERROR, "Failed to query subscription", err))
|
||||
}
|
||||
if !sub.Confirmed {
|
||||
return langext.Ptr(ginresp.APIError(ac.ginContext, 401, apierr.USER_AUTH_FAILED, "You are not authorized for this action", nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return langext.Ptr(ginresp.APIError(ac.ginContext, 401, apierr.USER_AUTH_FAILED, "You are not authorized for this action", nil))
|
||||
}
|
||||
|
||||
func (ac *AppContext) CheckPermissionUserAdmin(userid models.UserID) *ginresp.HTTPResponse {
|
||||
p := ac.permissions
|
||||
if p.UserID != nil && *p.UserID == userid && p.KeyType == models.PermKeyTypeUserAdmin {
|
||||
if p.Token != nil && p.Token.IsAdmin(userid) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return langext.Ptr(ginresp.APIError(ac.ginContext, 401, apierr.USER_AUTH_FAILED, "You are not authorized for this action", nil))
|
||||
}
|
||||
|
||||
func (ac *AppContext) CheckPermissionSend() *ginresp.HTTPResponse {
|
||||
p := ac.permissions
|
||||
if p.UserID != nil && p.KeyType == models.PermKeyTypeUserSend {
|
||||
return nil
|
||||
func (ac *AppContext) CheckPermissionSend(channel models.Channel, key string) (*models.KeyToken, *ginresp.HTTPResponse) {
|
||||
|
||||
keytok, err := ac.app.Database.Primary.GetKeyTokenByToken(ac, key)
|
||||
if err != nil {
|
||||
return nil, langext.Ptr(ginresp.APIError(ac.ginContext, 500, apierr.DATABASE_ERROR, "Failed to query token", err))
|
||||
}
|
||||
if p.UserID != nil && p.KeyType == models.PermKeyTypeUserAdmin {
|
||||
return nil
|
||||
if keytok == nil {
|
||||
return nil, langext.Ptr(ginresp.APIError(ac.ginContext, 401, apierr.USER_AUTH_FAILED, "You are not authorized for this action", nil))
|
||||
}
|
||||
|
||||
return langext.Ptr(ginresp.APIError(ac.ginContext, 401, apierr.USER_AUTH_FAILED, "You are not authorized for this action", nil))
|
||||
if keytok.IsChannelMessagesSend(channel) {
|
||||
return keytok, nil
|
||||
}
|
||||
|
||||
return nil, langext.Ptr(ginresp.APIError(ac.ginContext, 401, apierr.USER_AUTH_FAILED, "You are not authorized for this action", nil))
|
||||
}
|
||||
|
||||
func (ac *AppContext) CheckPermissionAny() *ginresp.HTTPResponse {
|
||||
func (ac *AppContext) CheckPermissionMessageRead(msg models.Message) bool {
|
||||
p := ac.permissions
|
||||
if p.KeyType == models.PermKeyTypeNone {
|
||||
return langext.Ptr(ginresp.APIError(ac.ginContext, 401, apierr.USER_AUTH_FAILED, "You are not authorized for this action", nil))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ac *AppContext) CheckPermissionMessageReadDirect(msg models.Message) bool {
|
||||
p := ac.permissions
|
||||
if p.UserID != nil && msg.OwnerUserID == *p.UserID && p.KeyType == models.PermKeyTypeUserRead {
|
||||
return true
|
||||
}
|
||||
if p.UserID != nil && msg.OwnerUserID == *p.UserID && p.KeyType == models.PermKeyTypeUserAdmin {
|
||||
if p.Token != nil && p.Token.IsChannelMessagesRead(msg.ChannelID) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (ac *AppContext) CheckPermissionAny() *ginresp.HTTPResponse {
|
||||
p := ac.permissions
|
||||
if p.Token == nil {
|
||||
return langext.Ptr(ginresp.APIError(ac.ginContext, 401, apierr.USER_AUTH_FAILED, "You are not authorized for this action", nil))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ac *AppContext) GetPermissionUserID() *models.UserID {
|
||||
if ac.permissions.UserID == nil {
|
||||
if ac.permissions.Token == nil {
|
||||
return nil
|
||||
} else {
|
||||
return langext.Ptr(*ac.permissions.UserID)
|
||||
return langext.Ptr(ac.permissions.Token.OwnerUserID)
|
||||
}
|
||||
}
|
||||
|
||||
func (ac *AppContext) IsPermissionUserRead() bool {
|
||||
p := ac.permissions
|
||||
return p.KeyType == models.PermKeyTypeUserRead || p.KeyType == models.PermKeyTypeUserAdmin
|
||||
}
|
||||
|
||||
func (ac *AppContext) IsPermissionUserSend() bool {
|
||||
p := ac.permissions
|
||||
return p.KeyType == models.PermKeyTypeUserSend || p.KeyType == models.PermKeyTypeUserAdmin
|
||||
}
|
||||
|
||||
func (ac *AppContext) IsPermissionUserAdmin() bool {
|
||||
p := ac.permissions
|
||||
return p.KeyType == models.PermKeyTypeUserAdmin
|
||||
func (ac *AppContext) GetPermissionKeyTokenID() *models.KeyTokenID {
|
||||
if ac.permissions.Token == nil {
|
||||
return nil
|
||||
} else {
|
||||
return langext.Ptr(ac.permissions.Token.KeyTokenID)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user