Browse Source

Fix #25

dependabot/npm_and_yarn/web/prismjs-1.21.0
Max Schmitt 8 years ago
parent
commit
dbdcfa0f68
  1. 3
      .travis.yml
  2. 3
      handlers/public.go
  3. 76
      static/src/Home/Home.js
  4. 8
      store/store.go
  5. 16
      store/util.go

3
.travis.yml

@ -18,3 +18,6 @@ deploy:
file: "descriptor.json"
key:
secure: ErqvSFIlL3d9XuMj+T+hO6xZqll8Ubx0DEdHD6NJKi7sH7Be3b3/vUoPdAjdFOP70DhaccbncGCTPZ9hsNKdqYxZmuKx3WWwH4H4U5YdDIViXtH6+B5KdAmvdZIynaj+THQAbVAhr+QyvcqotNySPd3Ac1HCg2YAcUHme6y3FsiRJ79To80JWxTSR1G/oObmeoDn8R18wmH1gHl8KQ7ltC537Osb/H34bJ/hY94hRe8IEmoQE4yz/EP44kGXRb/F87i92y1mO081ZS1I1hs5Kbom43YoItqSVbJP/abPMyCsGDv2FGXaGqk5IVC1k+01pcAjqxCzMvXC272itc0E8OEWqE4qONN+m2S9tyALyOaUZ7j5meWLHQj49Rzo7XIWh1PvvEMovdl/wk/Oc9f0ZywPuvoRht5ZebgXbPWAMMNywwy0GKM4nU0DCyFm23mlzPh4iklo12gEUzq3YLc18RhAZuy4timeevrDCuJMQeQ3sqcQBKCQ+rdOxzVCKKl2sGpNaTJEYaHGT9KLCEGBLmvaB58RKgmGN6IIEwpxSm2SGoirfnQsr+DP+kaSvWPr6R/pZAhO1JzO+azaXvfr+hL2SMX6U7j5+SDmFGIFDwxok7ny1QUTQXKlNzA/ks9/vufe30hrTkph/MfEvM5mYVbfgAn5zZ0v+dJ2wCoe1go=
notifications:
webhooks:
- https://ws.b0n.pl/relaunch

3
handlers/public.go

@ -11,6 +11,7 @@ import (
// un- and marshalling
type URLUtil struct {
URL string `binding:"required"`
ID string
}
// handleLookup is the http handler for getting the infos
@ -74,7 +75,7 @@ func (h *Handler) handleCreate(c *gin.Context) {
RemoteAddr: c.ClientIP(),
OAuthProvider: user.OAuthProvider,
OAuthID: user.OAuthID,
})
}, data.ID)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return

76
static/src/Home/Home.js

@ -1,45 +1,83 @@
import React, { Component } from 'react'
import { Input, Segment, Form, Header, Card } from 'semantic-ui-react'
import { Input, Segment, Form, Header, Card, Button, Select, Icon } from 'semantic-ui-react'
import CustomCard from '../Card/Card'
export default class HomeComponent extends Component {
handleURLChange = (e, { value }) => this.url = value
state = {
links: []
}
componentDidMount() {
this.urlInput.focus()
}
handleURLSubmit = () => {
fetch('/api/v1/protected/create', {
method: 'POST',
handleCustomIDChange = (e, { value }) => {
this.customID = value
fetch("/api/v1/protected/lookup", {
method: "POST",
body: JSON.stringify({
URL: this.url
ID: value
}),
headers: {
'Authorization': window.localStorage.getItem('token'),
'Content-Type': 'application/json'
}
}).then(res => res.ok ? res.json() : Promise.reject(res.json()))
.then(r => this.setState({
links: [...this.state.links, [
r.URL,
this.url
]]
}))
.then(() => {
this.setState({ showCustomIDError: true })
})
.catch(() => this.setState({ showCustomIDError: false }))
}
onSettingsChange = (e, { value }) => this.setState({ setOptions: value })
state = {
links: [],
options: [
{ text: 'Custom URL', value: 'custom' },
{ text: 'Expiration', value: 'expire' }
],
setOptions: [],
showCustomIDError: false
}
componentDidMount() {
this.urlInput.focus()
}
handleURLSubmit = () => {
if (!this.state.showCustomIDError) {
fetch('/api/v1/protected/create', {
method: 'POST',
body: JSON.stringify({
URL: this.url,
ID: this.customID
}),
headers: {
'Authorization': window.localStorage.getItem('token'),
'Content-Type': 'application/json'
}
}).then(res => res.ok ? res.json() : Promise.reject(res.json()))
.then(r => this.setState({
links: [...this.state.links, [
r.URL,
this.url
]]
}))
}
}
render() {
const { links } = this.state
const { links, options, setOptions, showCustomIDError } = this.state
return (
<div>
<Segment raised>
<Header size='huge'>Simplify your links</Header>
<Form onSubmit={this.handleURLSubmit} autoComplete="off">
<Form.Field>
<Input required size='big' ref={input => this.urlInput = input} action={{ icon: 'arrow right', labelPosition: 'right', content: 'Shorten' }} type='url' onChange={this.handleURLChange} name='url' placeholder='Paste a link to shorten it' />
<Input required size='large' type='url' ref={input => this.urlInput = input} onChange={this.handleURLChange} placeholder='Paste a link to shorten it' action>
<input />
<Select options={options} placeholder='Settings' onChange={this.onSettingsChange} multiple />
<Button type='submit'>Shorten<Icon name="arrow right" /></Button>
</Input>
</Form.Field>
<Form.Group widths='equal'>
{setOptions.indexOf("custom") > -1 && <Form.Field error={showCustomIDError}><Input label={window.location.origin + "/"} onChange={this.handleCustomIDChange} placeholder='my-shortened-url' />
</Form.Field>
}
</Form.Group>
</Form>
</Segment>
<Card.Group itemsPerRow="2">

8
store/store.go

@ -116,14 +116,16 @@ func (s *Store) GetEntryByIDRaw(id string) ([]byte, error) {
}
// CreateEntry creates a new record and returns his short id
func (s *Store) CreateEntry(entry Entry) (string, error) {
func (s *Store) CreateEntry(entry Entry, givenID string) (string, error) {
if !govalidator.IsURL(entry.Public.URL) {
return "", ErrNoValidURL
}
// try it 10 times to make a short URL
for i := 1; i <= 10; i++ {
id, err := s.createEntry(entry)
if err != nil {
id, err := s.createEntry(entry, givenID)
if err != nil && givenID != "" {
return "", err
} else if err != nil {
s.log.Debugf("Could not create entry: %v", err)
continue
}

16
store/util.go

@ -17,7 +17,7 @@ func (s *Store) createEntryRaw(key, value []byte) error {
bucket := tx.Bucket(s.bucketName)
raw := bucket.Get(key)
if raw != nil {
return errors.New("entry value is not empty")
return errors.New("entry already exists")
}
if err := bucket.Put(key, value); err != nil {
return errors.Wrap(err, "could not put data into bucket")
@ -28,10 +28,16 @@ func (s *Store) createEntryRaw(key, value []byte) error {
}
// createEntry creates a new entry
func (s *Store) createEntry(entry Entry) (string, error) {
id, err := generateRandomString(s.idLength)
if err != nil {
return "", errors.Wrap(err, "could not generate random string")
func (s *Store) createEntry(entry Entry, givenID string) (string, error) {
var id string
var err error
if givenID != "" {
id = givenID
} else {
id, err = generateRandomString(s.idLength)
if err != nil {
return "", errors.Wrap(err, "could not generate random string")
}
}
entry.Public.CreatedOn = time.Now()
raw, err := json.Marshal(entry)

Loading…
Cancel
Save