mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-12-20 16:06:15 -06:00
get individual domain block, delete a block
This commit is contained in:
parent
6f20eaee75
commit
8475898b75
18 changed files with 213 additions and 16 deletions
|
|
@ -35,9 +35,13 @@ const (
|
||||||
EmojiPath = BasePath + "/custom_emojis"
|
EmojiPath = BasePath + "/custom_emojis"
|
||||||
// DomainBlocksPath is used for posting domain blocks.
|
// DomainBlocksPath is used for posting domain blocks.
|
||||||
DomainBlocksPath = BasePath + "/domain_blocks"
|
DomainBlocksPath = BasePath + "/domain_blocks"
|
||||||
|
// DomainBlockPath is used for interacting with a single domain block.
|
||||||
|
DomainBlockPath = DomainBlocksPath + "/:" + IDKey
|
||||||
|
|
||||||
// ExportQueryKey is the key to use when requesting a public export of some data.
|
// ExportQueryKey is for requesting a public export of some data.
|
||||||
ExportQueryKey = "export"
|
ExportQueryKey = "export"
|
||||||
|
// IDKey specifies the ID of a single item being interacted with.
|
||||||
|
IDKey = "id"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Module implements the ClientAPIModule interface for admin-related actions (reports, emojis, etc)
|
// Module implements the ClientAPIModule interface for admin-related actions (reports, emojis, etc)
|
||||||
|
|
@ -61,5 +65,7 @@ func (m *Module) Route(r router.Router) error {
|
||||||
r.AttachHandler(http.MethodPost, EmojiPath, m.emojiCreatePOSTHandler)
|
r.AttachHandler(http.MethodPost, EmojiPath, m.emojiCreatePOSTHandler)
|
||||||
r.AttachHandler(http.MethodPost, DomainBlocksPath, m.DomainBlocksPOSTHandler)
|
r.AttachHandler(http.MethodPost, DomainBlocksPath, m.DomainBlocksPOSTHandler)
|
||||||
r.AttachHandler(http.MethodGet, DomainBlocksPath, m.DomainBlocksGETHandler)
|
r.AttachHandler(http.MethodGet, DomainBlocksPath, m.DomainBlocksGETHandler)
|
||||||
|
r.AttachHandler(http.MethodGet, DomainBlockPath, m.DomainBlockGETHandler)
|
||||||
|
r.AttachHandler(http.MethodDelete, DomainBlockPath, m.DomainBlockDELETEHandler)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DomainBlocksPOSTHandler deals with the creation of a new domain block.
|
||||||
func (m *Module) DomainBlocksPOSTHandler(c *gin.Context) {
|
func (m *Module) DomainBlocksPOSTHandler(c *gin.Context) {
|
||||||
l := m.log.WithFields(logrus.Fields{
|
l := m.log.WithFields(logrus.Fields{
|
||||||
"func": "DomainBlocksPOSTHandler",
|
"func": "DomainBlocksPOSTHandler",
|
||||||
|
|
@ -67,5 +68,3 @@ func validateCreateDomainBlock(form *model.DomainBlockCreateRequest) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
47
internal/api/client/admin/domainblockdelete.go
Normal file
47
internal/api/client/admin/domainblockdelete.go
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
package admin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DomainBlockDELETEHandler deals with the delete of an existing domain block.
|
||||||
|
func (m *Module) DomainBlockDELETEHandler(c *gin.Context) {
|
||||||
|
l := m.log.WithFields(logrus.Fields{
|
||||||
|
"func": "DomainBlockDELETEHandler",
|
||||||
|
"request_uri": c.Request.RequestURI,
|
||||||
|
"user_agent": c.Request.UserAgent(),
|
||||||
|
"origin_ip": c.ClientIP(),
|
||||||
|
})
|
||||||
|
|
||||||
|
// make sure we're authed with an admin account
|
||||||
|
authed, err := oauth.Authed(c, true, true, true, true)
|
||||||
|
if err != nil {
|
||||||
|
l.Debugf("couldn't auth: %s", err)
|
||||||
|
c.JSON(http.StatusForbidden, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !authed.User.Admin {
|
||||||
|
l.Debugf("user %s not an admin", authed.User.ID)
|
||||||
|
c.JSON(http.StatusForbidden, gin.H{"error": "not an admin"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
domainBlockID := c.Param(IDKey)
|
||||||
|
if domainBlockID == "" {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": "no domain block id provided"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
domainBlock, errWithCode := m.processor.AdminDomainBlockDelete(authed, domainBlockID)
|
||||||
|
if errWithCode != nil {
|
||||||
|
l.Debugf("error deleting domain block: %s", errWithCode.Error())
|
||||||
|
c.JSON(errWithCode.Code(), gin.H{"error": errWithCode.Safe()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, domainBlock)
|
||||||
|
}
|
||||||
|
|
@ -9,9 +9,10 @@ import (
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (m *Module) DomainBlocksGETHandler(c *gin.Context) {
|
// DomainBlockGETHandler returns one existing domain block, identified by its id.
|
||||||
|
func (m *Module) DomainBlockGETHandler(c *gin.Context) {
|
||||||
l := m.log.WithFields(logrus.Fields{
|
l := m.log.WithFields(logrus.Fields{
|
||||||
"func": "DomainBlocksPOSTHandler",
|
"func": "DomainBlockGETHandler",
|
||||||
"request_uri": c.Request.RequestURI,
|
"request_uri": c.Request.RequestURI,
|
||||||
"user_agent": c.Request.UserAgent(),
|
"user_agent": c.Request.UserAgent(),
|
||||||
"origin_ip": c.ClientIP(),
|
"origin_ip": c.ClientIP(),
|
||||||
|
|
@ -30,6 +31,12 @@ func (m *Module) DomainBlocksGETHandler(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
domainBlockID := c.Param(IDKey)
|
||||||
|
if domainBlockID == "" {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": "no domain block id provided"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
export := false
|
export := false
|
||||||
exportString := c.Query(ExportQueryKey)
|
exportString := c.Query(ExportQueryKey)
|
||||||
if exportString != "" {
|
if exportString != "" {
|
||||||
|
|
@ -42,12 +49,12 @@ func (m *Module) DomainBlocksGETHandler(c *gin.Context) {
|
||||||
export = i
|
export = i
|
||||||
}
|
}
|
||||||
|
|
||||||
domainBlocks, err := m.processor.AdminDomainBlocksGet(authed, export)
|
domainBlock, err := m.processor.AdminDomainBlockGet(authed, domainBlockID, export)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.Debugf("error getting domain blocks: %s", err)
|
l.Debugf("error getting domain block: %s", err)
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, domainBlocks)
|
c.JSON(http.StatusOK, domainBlock)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
54
internal/api/client/admin/domainblocksget.go
Normal file
54
internal/api/client/admin/domainblocksget.go
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
package admin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DomainBlocksGETHandler returns a list of all existing domain blocks.
|
||||||
|
func (m *Module) DomainBlocksGETHandler(c *gin.Context) {
|
||||||
|
l := m.log.WithFields(logrus.Fields{
|
||||||
|
"func": "DomainBlocksGETHandler",
|
||||||
|
"request_uri": c.Request.RequestURI,
|
||||||
|
"user_agent": c.Request.UserAgent(),
|
||||||
|
"origin_ip": c.ClientIP(),
|
||||||
|
})
|
||||||
|
|
||||||
|
// make sure we're authed with an admin account
|
||||||
|
authed, err := oauth.Authed(c, true, true, true, true)
|
||||||
|
if err != nil {
|
||||||
|
l.Debugf("couldn't auth: %s", err)
|
||||||
|
c.JSON(http.StatusForbidden, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !authed.User.Admin {
|
||||||
|
l.Debugf("user %s not an admin", authed.User.ID)
|
||||||
|
c.JSON(http.StatusForbidden, gin.H{"error": "not an admin"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
export := false
|
||||||
|
exportString := c.Query(ExportQueryKey)
|
||||||
|
if exportString != "" {
|
||||||
|
i, err := strconv.ParseBool(exportString)
|
||||||
|
if err != nil {
|
||||||
|
l.Debugf("error parsing export string: %s", err)
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": "couldn't parse export query param"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
export = i
|
||||||
|
}
|
||||||
|
|
||||||
|
domainBlocks, err := m.processor.AdminDomainBlocksGet(authed, export)
|
||||||
|
if err != nil {
|
||||||
|
l.Debugf("error getting domain blocks: %s", err)
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, domainBlocks)
|
||||||
|
}
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
"github.com/superseriousbusiness/gotosocial/internal/oauth"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// InstanceUpdatePATCHHandler allows an admin to update the instance information served at /api/v1/instance
|
||||||
func (m *Module) InstanceUpdatePATCHHandler(c *gin.Context) {
|
func (m *Module) InstanceUpdatePATCHHandler(c *gin.Context) {
|
||||||
l := m.log.WithField("func", "InstanceUpdatePATCHHandler")
|
l := m.log.WithField("func", "InstanceUpdatePATCHHandler")
|
||||||
authed, err := oauth.Authed(c, true, true, true, true)
|
authed, err := oauth.Authed(c, true, true, true, true)
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,9 @@ import (
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/util"
|
"github.com/superseriousbusiness/gotosocial/internal/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// SignatureCheck checks whether an incoming http request has been signed. If so, it will check if the domain
|
||||||
|
// that signed the request is permitted to access the server. If it is permitted, the handler will set the key
|
||||||
|
// verifier in the gin context for use down the line.
|
||||||
func (m *Module) SignatureCheck(c *gin.Context) {
|
func (m *Module) SignatureCheck(c *gin.Context) {
|
||||||
l := m.log.WithField("func", "DomainBlockChecker")
|
l := m.log.WithField("func", "DomainBlockChecker")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -235,7 +235,7 @@ func (f *federator) Blocked(ctx context.Context, actorIRIs []*url.URL) (bool, er
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, uri := range actorIRIs {
|
for _, uri := range actorIRIs {
|
||||||
blockedDomain, err := f.blockedDomain(uri.Host);
|
blockedDomain, err := f.blockedDomain(uri.Host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("error checking domain block: %s", err)
|
return false, fmt.Errorf("error checking domain block: %s", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,3 +35,11 @@ func (p *processor) AdminDomainBlockCreate(authed *oauth.Auth, form *apimodel.Do
|
||||||
func (p *processor) AdminDomainBlocksGet(authed *oauth.Auth, export bool) ([]*apimodel.DomainBlock, gtserror.WithCode) {
|
func (p *processor) AdminDomainBlocksGet(authed *oauth.Auth, export bool) ([]*apimodel.DomainBlock, gtserror.WithCode) {
|
||||||
return p.adminProcessor.DomainBlocksGet(authed.Account, export)
|
return p.adminProcessor.DomainBlocksGet(authed.Account, export)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *processor) AdminDomainBlockGet(authed *oauth.Auth, id string, export bool) (*apimodel.DomainBlock, gtserror.WithCode) {
|
||||||
|
return p.adminProcessor.DomainBlockGet(authed.Account, id, export)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *processor) AdminDomainBlockDelete(authed *oauth.Auth, id string) (*apimodel.DomainBlock, gtserror.WithCode) {
|
||||||
|
return p.adminProcessor.DomainBlockDelete(authed.Account, id)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@ import (
|
||||||
type Processor interface {
|
type Processor interface {
|
||||||
DomainBlockCreate(account *gtsmodel.Account, form *apimodel.DomainBlockCreateRequest) (*apimodel.DomainBlock, gtserror.WithCode)
|
DomainBlockCreate(account *gtsmodel.Account, form *apimodel.DomainBlockCreateRequest) (*apimodel.DomainBlock, gtserror.WithCode)
|
||||||
DomainBlocksGet(account *gtsmodel.Account, export bool) ([]*apimodel.DomainBlock, gtserror.WithCode)
|
DomainBlocksGet(account *gtsmodel.Account, export bool) ([]*apimodel.DomainBlock, gtserror.WithCode)
|
||||||
|
DomainBlockGet(account *gtsmodel.Account, id string, export bool) (*apimodel.DomainBlock, gtserror.WithCode)
|
||||||
|
DomainBlockDelete(account *gtsmodel.Account, id string) (*apimodel.DomainBlock, gtserror.WithCode)
|
||||||
EmojiCreate(account *gtsmodel.Account, user *gtsmodel.User, form *apimodel.EmojiCreateRequest) (*apimodel.Emoji, error)
|
EmojiCreate(account *gtsmodel.Account, user *gtsmodel.User, form *apimodel.EmojiCreateRequest) (*apimodel.Emoji, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
36
internal/processing/admin/deletedomainblock.go
Normal file
36
internal/processing/admin/deletedomainblock.go
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
package admin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *processor) DomainBlockDelete(account *gtsmodel.Account, id string) (*apimodel.DomainBlock, gtserror.WithCode) {
|
||||||
|
domainBlock := >smodel.DomainBlock{}
|
||||||
|
|
||||||
|
if err := p.db.GetByID(id, domainBlock); err != nil {
|
||||||
|
if _, ok := err.(db.ErrNoEntries); !ok {
|
||||||
|
// something has gone really wrong
|
||||||
|
return nil, gtserror.NewErrorInternalError(err)
|
||||||
|
}
|
||||||
|
// there are no entries for this ID
|
||||||
|
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no entry for ID %s", id))
|
||||||
|
}
|
||||||
|
|
||||||
|
// prepare the domain block to return
|
||||||
|
mastoDomainBlock, err := p.tc.DomainBlockToMasto(domainBlock, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, gtserror.NewErrorInternalError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete the domain block
|
||||||
|
if err := p.db.DeleteByID(id, domainBlock); err != nil {
|
||||||
|
return nil, gtserror.NewErrorInternalError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return mastoDomainBlock, nil
|
||||||
|
}
|
||||||
30
internal/processing/admin/getdomainblock.go
Normal file
30
internal/processing/admin/getdomainblock.go
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
package admin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||||
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *processor) DomainBlockGet(account *gtsmodel.Account, id string, export bool) (*apimodel.DomainBlock, gtserror.WithCode) {
|
||||||
|
domainBlock := >smodel.DomainBlock{}
|
||||||
|
|
||||||
|
if err := p.db.GetByID(id, domainBlock); err != nil {
|
||||||
|
if _, ok := err.(db.ErrNoEntries); !ok {
|
||||||
|
// something has gone really wrong
|
||||||
|
return nil, gtserror.NewErrorInternalError(err)
|
||||||
|
}
|
||||||
|
// there are no entries for this ID
|
||||||
|
return nil, gtserror.NewErrorNotFound(fmt.Errorf("no entry for ID %s", id))
|
||||||
|
}
|
||||||
|
|
||||||
|
mastoDomainBlock, err := p.tc.DomainBlockToMasto(domainBlock, export)
|
||||||
|
if err != nil {
|
||||||
|
return nil, gtserror.NewErrorInternalError(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return mastoDomainBlock, nil
|
||||||
|
}
|
||||||
|
|
@ -22,10 +22,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/media"
|
"github.com/superseriousbusiness/gotosocial/internal/media"
|
||||||
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *processor) GetFile(account *gtsmodel.Account, form *apimodel.GetContentRequestForm) (*apimodel.Content, error) {
|
func (p *processor) GetFile(account *gtsmodel.Account, form *apimodel.GetContentRequestForm) (*apimodel.Content, error) {
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,10 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/db"
|
"github.com/superseriousbusiness/gotosocial/internal/db"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
"github.com/superseriousbusiness/gotosocial/internal/gtserror"
|
||||||
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
|
||||||
apimodel "github.com/superseriousbusiness/gotosocial/internal/api/model"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *processor) Update(account *gtsmodel.Account, mediaAttachmentID string, form *apimodel.AttachmentUpdateRequest) (*apimodel.Attachment, gtserror.WithCode) {
|
func (p *processor) Update(account *gtsmodel.Account, mediaAttachmentID string, form *apimodel.AttachmentUpdateRequest) (*apimodel.Attachment, gtserror.WithCode) {
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,10 @@ type Processor interface {
|
||||||
AdminDomainBlockCreate(authed *oauth.Auth, form *apimodel.DomainBlockCreateRequest) (*apimodel.DomainBlock, gtserror.WithCode)
|
AdminDomainBlockCreate(authed *oauth.Auth, form *apimodel.DomainBlockCreateRequest) (*apimodel.DomainBlock, gtserror.WithCode)
|
||||||
// AdminDomainBlocksGet returns a list of currently blocked domains.
|
// AdminDomainBlocksGet returns a list of currently blocked domains.
|
||||||
AdminDomainBlocksGet(authed *oauth.Auth, export bool) ([]*apimodel.DomainBlock, gtserror.WithCode)
|
AdminDomainBlocksGet(authed *oauth.Auth, export bool) ([]*apimodel.DomainBlock, gtserror.WithCode)
|
||||||
|
// AdminDomainBlockGet returns one domain block, specified by ID.
|
||||||
|
AdminDomainBlockGet(authed *oauth.Auth, id string, export bool) (*apimodel.DomainBlock, gtserror.WithCode)
|
||||||
|
// AdminDomainBlockDelete deletes one domain block, specified by ID, returning the deleted domain block.
|
||||||
|
AdminDomainBlockDelete(authed *oauth.Auth, id string) (*apimodel.DomainBlock, gtserror.WithCode)
|
||||||
|
|
||||||
// AppCreate processes the creation of a new API application
|
// AppCreate processes the creation of a new API application
|
||||||
AppCreate(authed *oauth.Auth, form *apimodel.ApplicationCreateRequest) (*apimodel.Application, error)
|
AppCreate(authed *oauth.Auth, form *apimodel.ApplicationCreateRequest) (*apimodel.Application, error)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue