mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-05-08 04:20:59 -05:00
generic http backend provisioning requests
Signed-off-by: Jörn Friedrich Dreyer <jfd@butonic.de>
This commit is contained in:
committed by
Daniël Franke
parent
5d7a19997b
commit
fc5e4ea7d1
@@ -18,16 +18,18 @@ type Config struct {
|
|||||||
|
|
||||||
HTTP HTTP `yaml:"http"`
|
HTTP HTTP `yaml:"http"`
|
||||||
|
|
||||||
|
Endpoint Endpoint `yaml:"enpoint"`
|
||||||
|
|
||||||
TokenManager *TokenManager `yaml:"token_manager"`
|
TokenManager *TokenManager `yaml:"token_manager"`
|
||||||
|
|
||||||
Context context.Context `yaml:"-"`
|
Context context.Context `yaml:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instance to use with a matching rule and titles
|
// Endpoint to use
|
||||||
type Instance struct {
|
type Endpoint struct {
|
||||||
Claim string `yaml:"claim"`
|
URL string `yaml:"url" env:"INVITATIONS_PROVISIONING_URL" desc:"The endpoint provisioning requests are sent to."`
|
||||||
Regex string `yaml:"regex"`
|
Method string `yaml:"method" env:"INVITATIONS_PROVISIONING_METHOD" desc:"The method to use when making provisioning requests."`
|
||||||
Href string `yaml:"href"`
|
BodyTemplate string `yaml:"body_template" env:"INVITATIONS_PROVISIONING_BODY_TEMPLATE" desc:"The template to use as body of a provisioning request."`
|
||||||
Titles map[string]string `yaml:"titles"`
|
Authorization string `yaml:"authorization" env:"INVITATIONS_PROVISIONING_AUTH" desc:"The authorization to use. Can be 'token' to reuse the access token or 'bearer' to send a static api token."`
|
||||||
Break bool `yaml:"break"`
|
Token string `yaml:"authorization" env:"INVITATIONS_PROVISIONING_AUTH" desc:"The bearer token to send in provisioning requests."`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,17 @@ func DefaultConfig() *config.Config {
|
|||||||
Service: config.Service{
|
Service: config.Service{
|
||||||
Name: "invitations",
|
Name: "invitations",
|
||||||
},
|
},
|
||||||
|
Endpoint: config.Endpoint{
|
||||||
|
URL: "{{.OCIS_URL}}/graph/v1.0/users",
|
||||||
|
Method: "POST",
|
||||||
|
BodyTemplate: `{
|
||||||
|
"inviteRedirectUrl": "{{.redirectUrl}}",
|
||||||
|
"invitedUserEmailAddress": "{{.mail}}",
|
||||||
|
"invitedUserDisplayName": "{{.displayName}}",
|
||||||
|
"sendInvitationMessage": true
|
||||||
|
}`,
|
||||||
|
Authorization: "token", // reuse existing token
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
libregraph "github.com/owncloud/libre-graph-api-go"
|
libregraph "github.com/owncloud/libre-graph-api-go"
|
||||||
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
"github.com/owncloud/ocis/v2/ocis-pkg/log"
|
||||||
@@ -41,15 +44,24 @@ type Service interface {
|
|||||||
func New(opts ...Option) (Service, error) {
|
func New(opts ...Option) (Service, error) {
|
||||||
options := newOptions(opts...)
|
options := newOptions(opts...)
|
||||||
|
|
||||||
|
urlTemplate, err := template.New("invitations-provisioning-endpoint-url").Parse(options.Config.Endpoint.URL)
|
||||||
|
bodyTemplate, err := template.New("invitations-provisioning-endpoint-url").Parse(options.Config.Endpoint.BodyTemplate)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
return svc{
|
return svc{
|
||||||
log: options.Logger,
|
log: options.Logger,
|
||||||
config: options.Config,
|
config: options.Config,
|
||||||
|
urlTemplate: urlTemplate,
|
||||||
|
bodyTemplate: bodyTemplate,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type svc struct {
|
type svc struct {
|
||||||
config *config.Config
|
config *config.Config
|
||||||
log log.Logger
|
log log.Logger
|
||||||
|
urlTemplate *template.Template
|
||||||
|
bodyTemplate *template.Template
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invite implements the service interface
|
// Invite implements the service interface
|
||||||
@@ -74,8 +86,21 @@ func (s svc) Invite(ctx context.Context, invitation *invitations.Invitation) (*i
|
|||||||
// we don't really need a username as guests have to log in with their email address anyway
|
// we don't really need a username as guests have to log in with their email address anyway
|
||||||
// what if later a user is provisioned with a guest accounts email address?
|
// what if later a user is provisioned with a guest accounts email address?
|
||||||
|
|
||||||
data, err := json.Marshal(user)
|
templateVars := map[string]string{
|
||||||
if err != nil {
|
"redirectUrl": invitation.InviteRedirectUrl,
|
||||||
|
// TODO message and other options
|
||||||
|
"mail": invitation.InvitedUserEmailAddress,
|
||||||
|
"displayName": invitation.InvitedUserDisplayName,
|
||||||
|
"userType": invitation.InvitedUserType,
|
||||||
|
}
|
||||||
|
|
||||||
|
var urlWriter strings.Builder
|
||||||
|
if err := s.urlTemplate.Execute(&urlWriter, templateVars); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var bodyWriter strings.Builder
|
||||||
|
if err := s.bodyTemplate.Execute(&bodyWriter, templateVars); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,13 +110,20 @@ func (s svc) Invite(ctx context.Context, invitation *invitations.Invitation) (*i
|
|||||||
}
|
}
|
||||||
client := &http.Client{Transport: tr}
|
client := &http.Client{Transport: tr}
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", "/graph/v1.0/users", bytes.NewReader(data))
|
req, err := http.NewRequest(s.config.Endpoint.Method, urlWriter.String(), bytes.NewBufferString(bodyWriter.String()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO either forward current user token or use bearer token?
|
// TODO either forward current user token or use bearer token?
|
||||||
req.Header.Set("Authorization", "Bearer some-token")
|
switch s.config.Endpoint.Authorization {
|
||||||
|
case "token":
|
||||||
|
// TODO forward current reva access token
|
||||||
|
case "bearer":
|
||||||
|
req.Header.Set("Authorization", "Bearer "+s.config.Endpoint.Token)
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unknown authorization: " + s.config.Endpoint.Authorization)
|
||||||
|
}
|
||||||
|
|
||||||
res, err := client.Do(req)
|
res, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -99,6 +131,15 @@ func (s svc) Invite(ctx context.Context, invitation *invitations.Invitation) (*i
|
|||||||
}
|
}
|
||||||
defer res.Body.Close()
|
defer res.Body.Close()
|
||||||
|
|
||||||
|
// TODO hm ok so we expect the rosponse to be a libregraph user ... so much for a generic endpoint
|
||||||
|
// we could try parsing into a map[string]interface{} .... hm ... maybe better to be specific about
|
||||||
|
// the actual backend: libregraph, keycloak, scim or even oc10?
|
||||||
|
|
||||||
|
// Or we remember the mail of the user in memory and try to check if the user is already avilable via
|
||||||
|
// a local user api ... hm ... graph or cs3 user backend now?
|
||||||
|
|
||||||
|
// in any case this will require an additional endpoint to keep track of the ongoing invitations
|
||||||
|
|
||||||
invitedUser := &libregraph.User{}
|
invitedUser := &libregraph.User{}
|
||||||
err = json.NewDecoder(res.Body).Decode(invitedUser)
|
err = json.NewDecoder(res.Body).Decode(invitedUser)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user