mirror of https://github.com/pikami/cosmium.git
Fixed authentication key generation for partition key ranges
Fixed collection rid generation Improved compatibility with SDKs
This commit is contained in:
parent
ec5f82cd54
commit
0cec7816c1
|
@ -1,6 +1,7 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
@ -15,6 +16,7 @@ func GetAllCollections(c *gin.Context) {
|
||||||
if status == repositorymodels.StatusOk {
|
if status == repositorymodels.StatusOk {
|
||||||
database, _ := repositories.GetDatabase(databaseId)
|
database, _ := repositories.GetDatabase(databaseId)
|
||||||
|
|
||||||
|
c.Header("x-ms-item-count", fmt.Sprintf("%d", len(collections)))
|
||||||
c.IndentedJSON(http.StatusOK, gin.H{
|
c.IndentedJSON(http.StatusOK, gin.H{
|
||||||
"_rid": database.ResourceID,
|
"_rid": database.ResourceID,
|
||||||
"DocumentCollections": collections,
|
"DocumentCollections": collections,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
@ -11,6 +12,7 @@ import (
|
||||||
func GetAllDatabases(c *gin.Context) {
|
func GetAllDatabases(c *gin.Context) {
|
||||||
databases, status := repositories.GetAllDatabases()
|
databases, status := repositories.GetAllDatabases()
|
||||||
if status == repositorymodels.StatusOk {
|
if status == repositorymodels.StatusOk {
|
||||||
|
c.Header("x-ms-item-count", fmt.Sprintf("%d", len(databases)))
|
||||||
c.IndentedJSON(http.StatusOK, gin.H{
|
c.IndentedJSON(http.StatusOK, gin.H{
|
||||||
"_rid": "",
|
"_rid": "",
|
||||||
"Databases": databases,
|
"Databases": databases,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
@ -17,6 +18,7 @@ func GetAllDocuments(c *gin.Context) {
|
||||||
if status == repositorymodels.StatusOk {
|
if status == repositorymodels.StatusOk {
|
||||||
collection, _ := repositories.GetCollection(databaseId, collectionId)
|
collection, _ := repositories.GetCollection(databaseId, collectionId)
|
||||||
|
|
||||||
|
c.Header("x-ms-item-count", fmt.Sprintf("%d", len(documents)))
|
||||||
c.IndentedJSON(http.StatusOK, gin.H{
|
c.IndentedJSON(http.StatusOK, gin.H{
|
||||||
"_rid": collection.ID,
|
"_rid": collection.ID,
|
||||||
"Documents": documents,
|
"Documents": documents,
|
||||||
|
@ -128,6 +130,7 @@ func DocumentsPost(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
collection, _ := repositories.GetCollection(databaseId, collectionId)
|
collection, _ := repositories.GetCollection(databaseId, collectionId)
|
||||||
|
c.Header("x-ms-item-count", fmt.Sprintf("%d", len(docs)))
|
||||||
c.IndentedJSON(http.StatusOK, gin.H{
|
c.IndentedJSON(http.StatusOK, gin.H{
|
||||||
"_rid": collection.ResourceID,
|
"_rid": collection.ResourceID,
|
||||||
"Documents": docs,
|
"Documents": docs,
|
||||||
|
|
|
@ -44,6 +44,11 @@ func Authentication() gin.HandlerFunc {
|
||||||
resourceId += "/docs/" + docId
|
resourceId += "/docs/" + docId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isFeed := c.Request.Header.Get("A-Im") == "Incremental Feed"
|
||||||
|
if resourceType == "pkranges" && isFeed {
|
||||||
|
resourceId = collId
|
||||||
|
}
|
||||||
|
|
||||||
authHeader := c.Request.Header.Get("authorization")
|
authHeader := c.Request.Header.Get("authorization")
|
||||||
date := c.Request.Header.Get("x-ms-date")
|
date := c.Request.Header.Get("x-ms-date")
|
||||||
expectedSignature := authentication.GenerateSignature(
|
expectedSignature := authentication.GenerateSignature(
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetOffers(c *gin.Context) {
|
func GetOffers(c *gin.Context) {
|
||||||
|
c.Header("x-ms-item-count", "0")
|
||||||
c.IndentedJSON(http.StatusOK, gin.H{
|
c.IndentedJSON(http.StatusOK, gin.H{
|
||||||
"_rid": "",
|
"_rid": "",
|
||||||
"_count": 0,
|
"_count": 0,
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
@ -15,6 +16,7 @@ func GetAllStoredProcedures(c *gin.Context) {
|
||||||
sps, status := repositories.GetAllStoredProcedures(databaseId, collectionId)
|
sps, status := repositories.GetAllStoredProcedures(databaseId, collectionId)
|
||||||
|
|
||||||
if status == repositorymodels.StatusOk {
|
if status == repositorymodels.StatusOk {
|
||||||
|
c.Header("x-ms-item-count", fmt.Sprintf("%d", len(sps)))
|
||||||
c.IndentedJSON(http.StatusOK, gin.H{"_rid": "", "StoredProcedures": sps, "_count": len(sps)})
|
c.IndentedJSON(http.StatusOK, gin.H{"_rid": "", "StoredProcedures": sps, "_count": len(sps)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
@ -15,6 +16,7 @@ func GetAllTriggers(c *gin.Context) {
|
||||||
triggers, status := repositories.GetAllTriggers(databaseId, collectionId)
|
triggers, status := repositories.GetAllTriggers(databaseId, collectionId)
|
||||||
|
|
||||||
if status == repositorymodels.StatusOk {
|
if status == repositorymodels.StatusOk {
|
||||||
|
c.Header("x-ms-item-count", fmt.Sprintf("%d", len(triggers)))
|
||||||
c.IndentedJSON(http.StatusOK, gin.H{"_rid": "", "Triggers": triggers, "_count": len(triggers)})
|
c.IndentedJSON(http.StatusOK, gin.H{"_rid": "", "Triggers": triggers, "_count": len(triggers)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package handlers
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
@ -15,6 +16,7 @@ func GetAllUserDefinedFunctions(c *gin.Context) {
|
||||||
udfs, status := repositories.GetAllUserDefinedFunctions(databaseId, collectionId)
|
udfs, status := repositories.GetAllUserDefinedFunctions(databaseId, collectionId)
|
||||||
|
|
||||||
if status == repositorymodels.StatusOk {
|
if status == repositorymodels.StatusOk {
|
||||||
|
c.Header("x-ms-item-count", fmt.Sprintf("%d", len(udfs)))
|
||||||
c.IndentedJSON(http.StatusOK, gin.H{"_rid": "", "UserDefinedFunctions": udfs, "_count": len(udfs)})
|
c.IndentedJSON(http.StatusOK, gin.H{"_rid": "", "UserDefinedFunctions": udfs, "_count": len(udfs)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,11 @@ import (
|
||||||
|
|
||||||
// https://learn.microsoft.com/en-us/rest/api/cosmos-db/access-control-on-cosmosdb-resources
|
// https://learn.microsoft.com/en-us/rest/api/cosmos-db/access-control-on-cosmosdb-resources
|
||||||
func GenerateSignature(verb string, resourceType string, resourceId string, date string, masterKey string) string {
|
func GenerateSignature(verb string, resourceType string, resourceId string, date string, masterKey string) string {
|
||||||
|
isNameBased := resourceId != "" && ((len(resourceId) > 4 && resourceId[3] == '/') || strings.HasPrefix(strings.ToLower(resourceId), "interopusers"))
|
||||||
|
if !isNameBased {
|
||||||
|
resourceId = strings.ToLower(resourceId)
|
||||||
|
}
|
||||||
|
|
||||||
payload := fmt.Sprintf(
|
payload := fmt.Sprintf(
|
||||||
"%s\n%s\n%s\n%s\n%s\n",
|
"%s\n%s\n%s\n%s\n%s\n",
|
||||||
strings.ToLower(verb),
|
strings.ToLower(verb),
|
||||||
|
|
|
@ -27,4 +27,9 @@ func Test_GenerateSignature(t *testing.T) {
|
||||||
signature := authentication.GenerateSignature("DELETE", "dbs", "dbs/Test Database", testDate, config.DefaultAccountKey)
|
signature := authentication.GenerateSignature("DELETE", "dbs", "dbs/Test Database", testDate, config.DefaultAccountKey)
|
||||||
assert.Equal(t, "LcuXXg0TcXxZG0kUCj9tZIWRy2yCzim3oiqGiHpRqGs=", signature)
|
assert.Equal(t, "LcuXXg0TcXxZG0kUCj9tZIWRy2yCzim3oiqGiHpRqGs=", signature)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("Should generate PKRANGES signature", func(t *testing.T) {
|
||||||
|
signature := authentication.GenerateSignature("GET", "pkranges", "m4d+xG08uVM=", testDate, config.DefaultAccountKey)
|
||||||
|
assert.Equal(t, "6S5ceZsl2EXWB3Jo5bJcK7zv8NxXnsxWPWD9TH3nNMo=", signature)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,8 @@ func CreateDocument(databaseId string, collectionId string, document map[string]
|
||||||
var database repositorymodels.Database
|
var database repositorymodels.Database
|
||||||
var collection repositorymodels.Collection
|
var collection repositorymodels.Collection
|
||||||
if documentId, ok = document["id"].(string); !ok || documentId == "" {
|
if documentId, ok = document["id"].(string); !ok || documentId == "" {
|
||||||
return repositorymodels.Document{}, repositorymodels.BadRequest
|
documentId = fmt.Sprint(uuid.New())
|
||||||
|
document["id"] = documentId
|
||||||
}
|
}
|
||||||
|
|
||||||
if database, ok = storeState.Databases[databaseId]; !ok {
|
if database, ok = storeState.Databases[databaseId]; !ok {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package resourceid
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"math/rand"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
|
@ -10,6 +11,12 @@ func New() string {
|
||||||
id := uuid.New().ID()
|
id := uuid.New().ID()
|
||||||
idBytes := uintToBytes(id)
|
idBytes := uintToBytes(id)
|
||||||
|
|
||||||
|
// first byte should be bigger than 0x80 for collection ids
|
||||||
|
// clients classify this id as "user" otherwise
|
||||||
|
if (idBytes[0] & 0x80) <= 0 {
|
||||||
|
idBytes[0] = byte(rand.Intn(0x80) + 0x80)
|
||||||
|
}
|
||||||
|
|
||||||
return base64.StdEncoding.EncodeToString(idBytes)
|
return base64.StdEncoding.EncodeToString(idBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue