thisnthat 5 years ago
commit
9e1c5c12af
3 changed files with 108 additions and 0 deletions
  1. 23 0
      discourse.go
  2. 49 0
      session.go
  3. 36 0
      sso.go

+ 23 - 0
discourse.go

@@ -0,0 +1,23 @@
+package discourse
+
+import "github.com/google/uuid"
+
+type SsoConfig struct {
+	endpoint       string
+	returnEndpoint string
+	secret         string
+	uuid           uuid.UUID
+}
+
+func GetSSORequestURL(config SsoConfig) string {
+	url := generateSSORequestURL(config)
+
+	return url
+}
+
+// ValidateSsoResponse - Validate the signature on the sso response
+func ValidateSsoResponse(config SsoConfig, sso string, sig string) bool {
+	ssoDataSig := computeHmac256(sso, config.secret)
+
+	return sig == ssoDataSig
+}

+ 49 - 0
session.go

@@ -0,0 +1,49 @@
+package discourse
+
+import (
+	"bytes"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"strconv"
+	"strings"
+)
+
+type Session struct {
+	apiKey      string
+	apiUser     string
+	apiEndpoint string
+}
+
+func (session Session) SendPM(usernames []string, title string, body string) (string, error) {
+	targetUsernames := strings.Join(usernames, ",")
+
+	messageJSON := map[string]interface{}{
+		"title":            title,
+		"target_usernames": targetUsernames,
+		"archetype":        "private_message",
+		"raw":              body,
+	}
+
+	payload, err := json.Marshal(messageJSON)
+	if err != nil {
+		return "", err
+	}
+
+	url := fmt.Sprintf("%s/posts.json?api_key=%s&api_username=%s", session.apiEndpoint, session.apiKey, session.apiUser)
+
+	response, err := http.Post(url, "application/json", bytes.NewBuffer(payload))
+
+	if err != nil {
+		return "", err
+	}
+
+	var result map[string]interface{}
+
+	json.NewDecoder(response.Body).Decode(&result)
+	topicIDDigit := result["topic_id"].(float64)
+
+	topicID := strconv.FormatFloat(topicIDDigit, 'f', -1, 64)
+
+	return topicID, nil
+}

+ 36 - 0
sso.go

@@ -0,0 +1,36 @@
+package discourse
+
+import (
+	"crypto/hmac"
+	"crypto/sha256"
+	"encoding/base64"
+	"encoding/hex"
+	"fmt"
+	"net/url"
+)
+
+func generateSSORequestURL(config SsoConfig) string {
+	// Build the query string payload
+	payload := fmt.Sprintf("nonce=%s&return_sso_url=%s", config.uuid, config.returnEndpoint)
+
+	// Base64 encode the payload
+	base64Payload := base64.StdEncoding.EncodeToString([]byte(payload))
+
+	// Urlencode the
+	URLEncodedPayload := url.QueryEscape(base64Payload)
+
+	// Get a hex signature for this payload with the sso secret
+	hexSignature := computeHmac256(base64Payload, config.secret)
+
+	ssoURL := fmt.Sprintf("%s?sso=%s&sig=%s", config.endpoint, URLEncodedPayload, hexSignature)
+
+	return ssoURL
+}
+
+// Create a hex signature from a message and secret
+func computeHmac256(message string, secret string) string {
+	key := []byte(secret)
+	h := hmac.New(sha256.New, key)
+	h.Write([]byte(message))
+	return hex.EncodeToString(h.Sum(nil))
+}