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. 48
      static/src/Home/Home.js
  4. 8
      store/store.go
  5. 12
      store/util.go

3
.travis.yml

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

48
static/src/Home/Home.js

@ -1,21 +1,48 @@
import React, { Component } from 'react' 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' import CustomCard from '../Card/Card'
export default class HomeComponent extends Component { export default class HomeComponent extends Component {
handleURLChange = (e, { value }) => this.url = value handleURLChange = (e, { value }) => this.url = value
handleCustomIDChange = (e, { value }) => {
this.customID = value
fetch("/api/v1/protected/lookup", {
method: "POST",
body: JSON.stringify({
ID: value
}),
headers: {
'Authorization': window.localStorage.getItem('token'),
'Content-Type': 'application/json'
}
}).then(res => res.ok ? res.json() : Promise.reject(res.json()))
.then(() => {
this.setState({ showCustomIDError: true })
})
.catch(() => this.setState({ showCustomIDError: false }))
}
onSettingsChange = (e, { value }) => this.setState({ setOptions: value })
state = { state = {
links: [] links: [],
options: [
{ text: 'Custom URL', value: 'custom' },
{ text: 'Expiration', value: 'expire' }
],
setOptions: [],
showCustomIDError: false
} }
componentDidMount() { componentDidMount() {
this.urlInput.focus() this.urlInput.focus()
} }
handleURLSubmit = () => { handleURLSubmit = () => {
if (!this.state.showCustomIDError) {
fetch('/api/v1/protected/create', { fetch('/api/v1/protected/create', {
method: 'POST', method: 'POST',
body: JSON.stringify({ body: JSON.stringify({
URL: this.url URL: this.url,
ID: this.customID
}), }),
headers: { headers: {
'Authorization': window.localStorage.getItem('token'), 'Authorization': window.localStorage.getItem('token'),
@ -29,17 +56,28 @@ export default class HomeComponent extends Component {
]] ]]
})) }))
} }
}
render() { render() {
const { links } = this.state const { links, options, setOptions, showCustomIDError } = this.state
return ( return (
<div> <div>
<Segment raised> <Segment raised>
<Header size='huge'>Simplify your links</Header> <Header size='huge'>Simplify your links</Header>
<Form onSubmit={this.handleURLSubmit} autoComplete="off"> <Form onSubmit={this.handleURLSubmit} autoComplete="off">
<Form.Field> <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.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> </Form>
</Segment> </Segment>
<Card.Group itemsPerRow="2"> <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 // 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) { if !govalidator.IsURL(entry.Public.URL) {
return "", ErrNoValidURL return "", ErrNoValidURL
} }
// try it 10 times to make a short URL // try it 10 times to make a short URL
for i := 1; i <= 10; i++ { for i := 1; i <= 10; i++ {
id, err := s.createEntry(entry) id, err := s.createEntry(entry, givenID)
if err != nil { if err != nil && givenID != "" {
return "", err
} else if err != nil {
s.log.Debugf("Could not create entry: %v", err) s.log.Debugf("Could not create entry: %v", err)
continue continue
} }

12
store/util.go

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

Loading…
Cancel
Save