Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Site accounts site-global settings #2738

Merged
merged 16 commits into from
Apr 19, 2022
5 changes: 5 additions & 0 deletions changelog/unreleased/siteacc-site-settings.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Enhancement: Site accounts site-global settings

This PR extends the site accounts service by adding site-global settings. These are used to store test user credentials that are in return used by our BBE port to perform CS3API-specific health checks.

https://github.com/cs3org/reva/pull/2738
25 changes: 21 additions & 4 deletions docs/content/en/docs/config/http/services/siteacc/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ prefix = "/siteacc"
{{< /highlight >}}
{{% /dir %}}

## Security settings
{{% dir name="creds_passphrase" type="string" default="" %}}
The passphrase to use when encoding stored credentials. Should be exactly 32 characters long.
{{< highlight toml >}}
[http.services.siteacc.security]
creds_passphrase = "supersecretpasswordthatyouknow!"
{{< /highlight >}}
{{% /dir %}}

## GOCDB settings
{{% dir name="url" type="string" default="" %}}
The external URL of the central GOCDB instance.
Expand Down Expand Up @@ -111,12 +120,20 @@ driver = "file"
{{< /highlight >}}
{{% /dir %}}

### Storage settings - File driver
{{% dir name="file" type="string" default="" %}}
The file location.
### Storage settings - File drivers
{{% dir name="sites_file" type="string" default="" %}}
The sites file location.
{{< highlight toml >}}
[http.services.siteacc.storage.file]
sites_file = "/var/reva/sites.json"
{{< /highlight >}}
{{% /dir %}}

{{% dir name="accounts_file" type="string" default="" %}}
The accounts file location.
{{< highlight toml >}}
[http.services.siteacc.storage.file]
file = "/var/reva/accounts.json"
accounts_file = "/var/reva/accounts.json"
{{< /highlight >}}
{{% /dir %}}

Expand Down
8 changes: 7 additions & 1 deletion examples/siteacc/siteacc.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
[http]
address = "0.0.0.0:9600"

# Security settings
[http.services.siteacc.security]
creds_passphrase = "superdupersecret"

# Connection to the GOCDB
[http.services.siteacc.gocdb]
url = "https://sciencemesh-test.uni-muenster.de/gocdb/"
write_url = "https://sciencemesh-test.uni-muenster.de/gocdbpi/"
Expand All @@ -10,7 +15,8 @@ apikey = "verysecret"
[http.services.siteacc.storage]
driver = "file"
[http.services.siteacc.storage.file]
file = "/var/revad/accounts.json"
sites_file = "/var/revad/sites.json"
accounts_file = "/var/revad/accounts.json"

# Email related settings
[http.services.siteacc.email]
Expand Down
60 changes: 44 additions & 16 deletions pkg/siteacc/account/manage/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
package manage

const tplJavaScript = `
function handleSettings() {
function handleAccountSettings() {
setState(STATE_STATUS, "Redirecting to the account settings...");
window.location.replace("{{getServerAddress}}/account/?path=settings");
}
Expand All @@ -29,9 +29,14 @@ function handleEditAccount() {
window.location.replace("{{getServerAddress}}/account/?path=edit");
}

function handleRequestAccess() {
function handleSiteSettings() {
setState(STATE_STATUS, "Redirecting to the site settings...");
window.location.replace("{{getServerAddress}}/account/?path=site");
}

function handleRequestAccess(scope) {
setState(STATE_STATUS, "Redirecting to the contact form...");
window.location.replace("{{getServerAddress}}/account/?path=contact&subject=" + encodeURIComponent("Request GOCDB access"));
window.location.replace("{{getServerAddress}}/account/?path=contact&subject=" + encodeURIComponent("Request " + scope + " access"));
}

function handleLogout() {
Expand All @@ -58,6 +63,9 @@ const tplStyleSheet = `
html * {
font-family: arial !important;
}
button {
min-width: 170px;
}
`

const tplBody = `
Expand All @@ -81,24 +89,44 @@ const tplBody = `
<div>
<strong>Account data:</strong>
<ul style="margin-top: 0em;">
<li>GOCDB access: <em>{{if .Account.Data.GOCDBAccess}}Granted{{else}}Not granted{{end}}</em></li>
<li>Site access: <em>{{if .Account.Data.SiteAccess}}Granted{{else}}Not granted{{end}}</em></li>
<li>GOCDB access: <em>{{if .Account.Data.GOCDBAccess}}Granted{{else}}Not granted{{end}}</em></li>
</ul>
</div>
<div>
<form id="form" method="POST" class="box" style="width: 100%;">
<button type="button" onClick="handleSettings();">Settings</button>
<button type="button" onClick="handleEditAccount();">Edit account</button>
<span style="width: 25px;">&nbsp;</span>
<button type="button" onClick="handleRequestAccess();" {{if .Account.Data.GOCDBAccess}}disabled{{end}}>Request GOCDB access</button>

<button type="button" onClick="handleLogout();" style="float: right;">Logout</button>
<div>
<button type="button" onClick="handleAccountSettings();">Account settings</button>
<button type="button" onClick="handleEditAccount();">Edit account</button>
<span style="width: 25px;">&nbsp;</span>

{{if .Account.Data.SiteAccess}}
<button type="button" onClick="handleSiteSettings();">Site settings</button>
<span style="width: 25px;">&nbsp;</span>
{{end}}

<button type="button" onClick="handleLogout();" style="float: right;">Logout</button>
</div>
<div style="margin-top: 0.5em;">
<button type="button" onClick="handleRequestAccess('Site');" {{if .Account.Data.SiteAccess}}disabled{{end}}>Request Site access</button>
<button type="button" onClick="handleRequestAccess('GOCDB');" {{if .Account.Data.GOCDBAccess}}disabled{{end}}>Request GOCDB access</button>
</div>
</form>
</div>
<div>
<p>Quick links:</p>
<ul>
<li><a href="https://gocdb.sciencemesh.uni-muenster.de" target="_blank">Central Database (GOCDB)</a></li>
<li><a href="https://developer.sciencemesh.io/docs/technical-documentation/central-database/" target="_blank">Central Database documentation</a></li>
</ul>
<div style="font-size: 90%; margin-top: 1em;">
<div>
<div>Notes:</div>
<ul style="margin-top: 0em;">
<li>The <em>Site access</em> allows you to access and modify the global configuration of your site.</li>
<li>The <em>GOCDB access</em> allows you to log into the central database where all site metadata is stored.</li>
</ul>
</div>
<div>
<div>Quick links:</div>
<ul style="margin-top: 0em;">
<li><a href="https://gocdb.sciencemesh.uni-muenster.de" target="_blank">Central Database (GOCDB)</a></li>
<li><a href="https://developer.sciencemesh.io/docs/technical-documentation/central-database/" target="_blank">Central Database documentation</a></li>
</ul>
</div>
</div>
`
52 changes: 43 additions & 9 deletions pkg/siteacc/account/panel.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/cs3org/reva/pkg/siteacc/account/manage"
"github.com/cs3org/reva/pkg/siteacc/account/registration"
"github.com/cs3org/reva/pkg/siteacc/account/settings"
"github.com/cs3org/reva/pkg/siteacc/account/site"
"github.com/cs3org/reva/pkg/siteacc/config"
"github.com/cs3org/reva/pkg/siteacc/data"
"github.com/cs3org/reva/pkg/siteacc/html"
Expand All @@ -50,6 +51,7 @@ const (
templateManage = "manage"
templateSettings = "settings"
templateEdit = "edit"
templateSite = "site"
templateContact = "contact"
templateRegistration = "register"
)
Expand Down Expand Up @@ -84,6 +86,10 @@ func (panel *Panel) initialize(conf *config.Configuration, log *zerolog.Logger)
return errors.Wrap(err, "unable to create the account editing template")
}

if err := panel.htmlPanel.AddTemplate(templateSite, &site.PanelTemplate{}); err != nil {
return errors.Wrap(err, "unable to create the site template")
}

if err := panel.htmlPanel.AddTemplate(templateContact, &contact.PanelTemplate{}); err != nil {
return errors.Wrap(err, "unable to create the contact template")
}
Expand All @@ -97,7 +103,7 @@ func (panel *Panel) initialize(conf *config.Configuration, log *zerolog.Logger)

// GetActiveTemplate returns the name of the active template.
func (panel *Panel) GetActiveTemplate(session *html.Session, path string) string {
validPaths := []string{templateLogin, templateManage, templateSettings, templateEdit, templateContact, templateRegistration}
validPaths := []string{templateLogin, templateManage, templateSettings, templateEdit, templateSite, templateContact, templateRegistration}
template := templateLogin

// Only allow valid template paths; redirect to the login page otherwise
Expand All @@ -113,18 +119,28 @@ func (panel *Panel) GetActiveTemplate(session *html.Session, path string) string

// PreExecute is called before the actual template is being executed.
func (panel *Panel) PreExecute(session *html.Session, path string, w http.ResponseWriter, r *http.Request) (html.ExecutionResult, error) {
protectedPaths := []string{templateManage, templateSettings, templateEdit, templateContact}
protectedPaths := []string{templateManage, templateSettings, templateEdit, templateSite, templateContact}

if user := session.LoggedInUser(); user != nil {
switch path {
case templateSite:
// If the logged in user doesn't have site access, redirect him back to the main account page
if !user.Account.Data.SiteAccess {
return panel.redirect(templateManage, w, r), nil
}

if session.LoggedInUser == nil {
case templateLogin:
case templateRegistration:
// If a user is logged in and tries to login or register again, redirect to the main account page
return panel.redirect(templateManage, w, r), nil
}
} else {
// If no user is logged in, redirect protected paths to the login page
for _, protected := range protectedPaths {
if protected == path {
return panel.redirect(templateLogin, w, r), nil
}
}
} else if path == templateLogin || path == templateRegistration {
// If a user is logged in and tries to login or register again, redirect to the main account page
return panel.redirect(templateManage, w, r), nil
}

return html.ContinueExecution, nil
Expand All @@ -144,19 +160,26 @@ func (panel *Panel) Execute(w http.ResponseWriter, r *http.Request, session *htm
}

type TemplateData struct {
Site *data.Site
Account *data.Account
Params map[string]string

Titles []string
Sites []data.SiteInformation
}

return TemplateData{
Account: session.LoggedInUser,
tplData := TemplateData{
Site: nil,
Account: nil,
Params: flatValues,
Titles: []string{"Mr", "Mrs", "Ms", "Prof", "Dr"},
Sites: availSites,
}
if user := session.LoggedInUser(); user != nil {
tplData.Site = panel.cloneUserSite(user.Site)
tplData.Account = user.Account
}
return tplData
}
return panel.htmlPanel.Execute(w, r, session, dataProvider)
}
Expand All @@ -179,11 +202,22 @@ func (panel *Panel) redirect(path string, w http.ResponseWriter, r *http.Request
return html.AbortExecution
}

func (panel *Panel) cloneUserSite(site *data.Site) *data.Site {
// Clone the user's site and decrypt the credentials for the panel
siteClone := site.Clone(true)
id, secret, err := site.Config.TestClientCredentials.Get(panel.conf.Security.CredentialsPassphrase)
if err == nil {
siteClone.Config.TestClientCredentials.ID = id
siteClone.Config.TestClientCredentials.Secret = secret
}
return siteClone
}

// NewPanel creates a new account panel.
func NewPanel(conf *config.Configuration, log *zerolog.Logger) (*Panel, error) {
form := &Panel{}
if err := form.initialize(conf, log); err != nil {
return nil, errors.Wrapf(err, "unable to initialize the account panel")
return nil, errors.Wrap(err, "unable to initialize the account panel")
}
return form, nil
}
2 changes: 1 addition & 1 deletion pkg/siteacc/account/settings/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ const tplBody = `
</div>
<div>&nbsp;</div>
<div>
<form id="form" method="POST" class="box container-inline" style="width: 100%;" onSubmit="handleAction('configure?invoker=user'); return false;">
<form id="form" method="POST" class="box container-inline" style="width: 100%;" onSubmit="handleAction('configure?invoker=user'); return false;">
<div style="grid-row: 1; grid-column: 1 / span 2;">
<h3>Notification settings</h3>
<hr>
Expand Down
51 changes: 51 additions & 0 deletions pkg/siteacc/account/site/site.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2018-2020 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// In applying this license, CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

package site

import "github.com/cs3org/reva/pkg/siteacc/html"

// PanelTemplate is the content provider for the edit form.
type PanelTemplate struct {
html.ContentProvider
}

// GetTitle returns the title of the panel.
func (template *PanelTemplate) GetTitle() string {
return "ScienceMesh Site Configuration"
}

// GetCaption returns the caption which is displayed on the panel.
func (template *PanelTemplate) GetCaption() string {
return "Configure your ScienceMesh Site!"
}

// GetContentJavaScript delivers additional JavaScript code.
func (template *PanelTemplate) GetContentJavaScript() string {
return tplJavaScript
}

// GetContentStyleSheet delivers additional stylesheet code.
func (template *PanelTemplate) GetContentStyleSheet() string {
return tplStyleSheet
}

// GetContentBody delivers the actual body content.
func (template *PanelTemplate) GetContentBody() string {
return tplBody
}
Loading