Browse Source

configurable app DisplayURL for the UI (#121)

* changes to enable custom 'display' URL in app

* making example.yml use an empty string for DisplayURL
dependabot/npm_and_yarn/web/prismjs-1.21.0
Jeff Billimek 7 years ago
committed by Max Schmitt
parent
commit
5c005ae890
  1. 3
      config/example.yaml
  2. 1
      internal/handlers/handlers.go
  3. 6
      internal/handlers/public.go
  4. 7
      internal/util/config.go
  5. 14
      web/src/Home/Home.js
  6. 14
      web/src/Lookup/Lookup.js
  7. 8
      web/src/Recent/Recent.js

3
config/example.yaml

@ -1,5 +1,6 @@
ListenAddr: ':8080' # Consists of 'IP:Port', e.g. ':8080' listens on any IP and on Port 8080
BaseURL: 'http://localhost:3000' # Origin URL, required for the authentication via OAuth
BaseURL: 'http://localhost:3000' # Origin URL, required for the authentication via OAuth callback
DisplayURL: '' # (OPTIONAL) Display URL, how the apication will present itself in the UI - if not set, defaults to BaseURL
Backend: boltdb # Can be 'boltdb' or 'redis'
DataDir: ./data # Contains: the database and the private key
EnableDebugMode: true # Activates more detailed logging

1
internal/handlers/handlers.go

@ -163,6 +163,7 @@ func (h *Handler) setHandlers() error {
h.engine.GET("/api/v1/info", h.handleInfo)
h.engine.GET("/d/:id/:hash", h.handleDelete)
h.engine.GET("/ok", h.handleHealthcheck)
h.engine.GET("/displayurl", h.handleDisplayURL)
// Handling the shorted URLs, if no one exists, it checks
// in the filesystem and sets headers for caching

6
internal/handlers/public.go

@ -162,6 +162,12 @@ func (h *Handler) handleInfo(c *gin.Context) {
c.JSON(http.StatusOK, out)
}
// handleDisplayURL returns the URL to use for display purposes
func (h *Handler) handleDisplayURL(c *gin.Context) {
out := util.GetConfig().DisplayURL
c.JSON(http.StatusOK, out)
}
func (h *Handler) handleRecent(c *gin.Context) {
user := c.MustGet("user").(*auth.JWTClaims)
entries, err := h.store.GetUserEntries(user.OAuthProvider, user.OAuthID)

7
internal/util/config.go

@ -16,6 +16,7 @@ import (
type Configuration struct {
ListenAddr string `yaml:"ListenAddr" env:"LISTEN_ADDR"`
BaseURL string `yaml:"BaseURL" env:"BASE_URL"`
DisplayURL string `yaml:"DisplayURL" env:"DISPLAY_URL"`
DataDir string `yaml:"DataDir" env:"DATA_DIR"`
Backend string `yaml:"Backend" env:"BACKEND"`
AuthBackend string `yaml:"AuthBackend" env:"AUTH_BACKEND"`
@ -58,6 +59,7 @@ type proxyAuthConf struct {
var Config = Configuration{
ListenAddr: ":8080",
BaseURL: "http://localhost:3000",
DisplayURL: "",
DataDir: "data",
Backend: "boltdb",
EnableDebugMode: false,
@ -110,6 +112,11 @@ func (o oAuthConf) Enabled() bool {
// GetConfig returns the configuration from the memory
func GetConfig() Configuration {
// if DisplayURL is not set in the config, default to BaseURL
if Config.DisplayURL == "" {
Config.DisplayURL = Config.BaseURL
}
return Config
}

14
web/src/Home/Home.js

@ -18,7 +18,8 @@ export default class HomeComponent extends Component {
usedSettings: this.urlParams.get('customUrl') ? ['custom'] : [],
customID: this.urlParams.get('customUrl') ? this.urlParams.get('customUrl') : '',
showCustomIDError: false,
expiration: null
expiration: null,
displayURL: window.location.origin
}
}
handleURLChange = (e, { value }) => this.url = value
@ -31,12 +32,13 @@ export default class HomeComponent extends Component {
onSettingsChange = (e, { value }) => {
this.setState({ usedSettings: value })
}
componentDidMount() {
this.urlInput.focus()
fetch("/displayurl")
.then(response => response.json())
.then(data => this.setState({displayURL: data}));
}
handleURLSubmit = () => {
if (!this.state.showCustomIDError) {
@ -47,7 +49,7 @@ export default class HomeComponent extends Component {
Password: this.state.usedSettings.includes("protected") && this.password ? this.password : undefined
}, r => this.setState({
links: [...this.state.links, {
shortenedURL: r.URL,
shortenedURL: this.state.displayURL + "/" + this.state.customID,
originalURL: this.url,
expiration: this.state.usedSettings.includes("expire") && this.state.expiration ? this.state.expiration.toISOString() : undefined,
deletionURL: r.DeletionURL
@ -89,7 +91,7 @@ export default class HomeComponent extends Component {
</MediaQuery>
<Form.Group style={{ marginBottom: "1rem" }}>
{usedSettings.includes("custom") && <Form.Field error={showCustomIDError} width={16}>
<Input label={window.location.origin + "/"} onChange={this.handleCustomIDChange} placeholder='my-shortened-url' value={this.state.customID}/>
<Input label={this.state.displayURL + "/"} onChange={this.handleCustomIDChange} placeholder='my-shortened-url' value={this.state.customID}/>
</Form.Field>}
</Form.Group>
<Form.Group widths="equal">

14
web/src/Lookup/Lookup.js

@ -6,15 +6,21 @@ import CustomCard from '../Card/Card'
export default class LookupComponent extends Component {
state = {
links: []
links: [],
displayURL: window.location.origin
}
componentDidMount() {
fetch("/displayurl")
.then(response => response.json())
.then(data => this.setState({displayURL: data}));
}
handleURLChange = (e, { value }) => this.url = value
handleURLSubmit = () => {
let id = this.url.replace(window.location.origin + "/", "")
let id = this.url.replace(this.state.displayURL + "/", "")
util.lookupEntry(id, res => this.setState({
links: [...this.state.links, [
res.URL,
this.url,
this.state.displayURL + "/" + this.url,
this.VisitCount,
res.CratedOn,
res.LastVisit,
@ -30,7 +36,7 @@ export default class LookupComponent extends Component {
<Header size='huge'>URL Lookup</Header>
<Form onSubmit={this.handleURLSubmit}>
<Form.Field>
<Input required size='big' ref={input => this.urlInput = input} action={{ icon: 'arrow right', labelPosition: 'right', content: 'Lookup' }} type='url' onChange={this.handleURLChange} name='url' placeholder={window.location.origin + "/..."} autoComplete="off" />
<Input required size='big' ref={input => this.urlInput = input} action={{ icon: 'arrow right', labelPosition: 'right', content: 'Lookup' }} type='text' label={this.state.displayURL + "/"} onChange={this.handleURLChange} name='url' placeholder={"short url"} autoComplete="off" />
</Form.Field>
</Form>
</Segment>

8
web/src/Recent/Recent.js

@ -8,11 +8,15 @@ import util from '../util/util'
export default class RecentComponent extends Component {
state = {
recent: []
recent: [],
displayURL: window.location.origin
}
componentDidMount() {
this.loadRecentURLs()
fetch("/displayurl")
.then(response => response.json())
.then(data => this.setState({displayURL: data}));
}
loadRecentURLs = () => {
@ -47,7 +51,7 @@ export default class RecentComponent extends Component {
}, {
Header: 'Short URL',
accessor: "ID",
Cell: props => `${window.location.origin}/${props.value}`
Cell: props => `${this.state.displayURL}/${props.value}`
}, {
Header: 'Visitor count',
accessor: "Public.VisitCount"

Loading…
Cancel
Save