first commit

This commit is contained in:
xmdhs 2023-09-01 21:07:22 +08:00
commit 6153ccee14
No known key found for this signature in database
GPG Key ID: E809D6D43DEFCC95
18 changed files with 540 additions and 0 deletions

116
db/mysql/db.go Normal file
View File

@ -0,0 +1,116 @@
// Code generated by sqlc. DO NOT EDIT.
package mysql
import (
"context"
"database/sql"
"fmt"
)
type DBTX interface {
ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
PrepareContext(context.Context, string) (*sql.Stmt, error)
QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
QueryRowContext(context.Context, string, ...interface{}) *sql.Row
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
func Prepare(ctx context.Context, db DBTX) (*Queries, error) {
q := Queries{db: db}
var err error
if q.createUserStmt, err = db.PrepareContext(ctx, createUser); err != nil {
return nil, fmt.Errorf("error preparing query CreateUser: %w", err)
}
if q.deleteUserStmt, err = db.PrepareContext(ctx, deleteUser); err != nil {
return nil, fmt.Errorf("error preparing query DeleteUser: %w", err)
}
if q.getUserStmt, err = db.PrepareContext(ctx, getUser); err != nil {
return nil, fmt.Errorf("error preparing query GetUser: %w", err)
}
if q.listUserStmt, err = db.PrepareContext(ctx, listUser); err != nil {
return nil, fmt.Errorf("error preparing query ListUser: %w", err)
}
return &q, nil
}
func (q *Queries) Close() error {
var err error
if q.createUserStmt != nil {
if cerr := q.createUserStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing createUserStmt: %w", cerr)
}
}
if q.deleteUserStmt != nil {
if cerr := q.deleteUserStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing deleteUserStmt: %w", cerr)
}
}
if q.getUserStmt != nil {
if cerr := q.getUserStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing getUserStmt: %w", cerr)
}
}
if q.listUserStmt != nil {
if cerr := q.listUserStmt.Close(); cerr != nil {
err = fmt.Errorf("error closing listUserStmt: %w", cerr)
}
}
return err
}
func (q *Queries) exec(ctx context.Context, stmt *sql.Stmt, query string, args ...interface{}) (sql.Result, error) {
switch {
case stmt != nil && q.tx != nil:
return q.tx.StmtContext(ctx, stmt).ExecContext(ctx, args...)
case stmt != nil:
return stmt.ExecContext(ctx, args...)
default:
return q.db.ExecContext(ctx, query, args...)
}
}
func (q *Queries) query(ctx context.Context, stmt *sql.Stmt, query string, args ...interface{}) (*sql.Rows, error) {
switch {
case stmt != nil && q.tx != nil:
return q.tx.StmtContext(ctx, stmt).QueryContext(ctx, args...)
case stmt != nil:
return stmt.QueryContext(ctx, args...)
default:
return q.db.QueryContext(ctx, query, args...)
}
}
func (q *Queries) queryRow(ctx context.Context, stmt *sql.Stmt, query string, args ...interface{}) *sql.Row {
switch {
case stmt != nil && q.tx != nil:
return q.tx.StmtContext(ctx, stmt).QueryRowContext(ctx, args...)
case stmt != nil:
return stmt.QueryRowContext(ctx, args...)
default:
return q.db.QueryRowContext(ctx, query, args...)
}
}
type Queries struct {
db DBTX
tx *sql.Tx
createUserStmt *sql.Stmt
deleteUserStmt *sql.Stmt
getUserStmt *sql.Stmt
listUserStmt *sql.Stmt
}
func (q *Queries) WithTx(tx *sql.Tx) *Queries {
return &Queries{
db: tx,
tx: tx,
createUserStmt: q.createUserStmt,
deleteUserStmt: q.deleteUserStmt,
getUserStmt: q.getUserStmt,
listUserStmt: q.listUserStmt,
}
}

22
db/mysql/models.go Normal file
View File

@ -0,0 +1,22 @@
// Code generated by sqlc. DO NOT EDIT.
package mysql
import ()
type Skin struct {
UserID int64 `db:"user_id"`
SkinHash string `db:"skin_hash"`
Type string `db:"type"`
Variant string `db:"variant"`
}
type User struct {
ID int64 `db:"id"`
Email string `db:"email"`
Password string `db:"password"`
Salt string `db:"salt"`
Disabled int32 `db:"disabled"`
Admin int32 `db:"admin"`
RegTime int64 `db:"reg_time"`
}

17
db/mysql/querier.go Normal file
View File

@ -0,0 +1,17 @@
// Code generated by sqlc. DO NOT EDIT.
package mysql
import (
"context"
"database/sql"
)
type Querier interface {
CreateUser(ctx context.Context, arg CreateUserParams) (sql.Result, error)
DeleteUser(ctx context.Context, id int64) error
GetUser(ctx context.Context, id int64) (User, error)
ListUser(ctx context.Context) ([]User, error)
}
var _ Querier = (*Queries)(nil)

124
db/mysql/query.sql.go Normal file
View File

@ -0,0 +1,124 @@
// Code generated by sqlc. DO NOT EDIT.
// source: query.sql
package mysql
import (
"context"
"database/sql"
)
const createUser = `-- name: CreateUser :execresult
INSERT INTO
user (
id,
email,
password,
salt,
disabled,
admin,
reg_time
)
VALUES
(?, ?, ?, ?, ?, ?, ?)
`
type CreateUserParams struct {
ID int64 `db:"id"`
Email string `db:"email"`
Password string `db:"password"`
Salt string `db:"salt"`
Disabled int32 `db:"disabled"`
Admin int32 `db:"admin"`
RegTime int64 `db:"reg_time"`
}
func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (sql.Result, error) {
return q.exec(ctx, q.createUserStmt, createUser,
arg.ID,
arg.Email,
arg.Password,
arg.Salt,
arg.Disabled,
arg.Admin,
arg.RegTime,
)
}
const deleteUser = `-- name: DeleteUser :exec
DELETE FROM
user
WHERE
id = ?
`
func (q *Queries) DeleteUser(ctx context.Context, id int64) error {
_, err := q.exec(ctx, q.deleteUserStmt, deleteUser, id)
return err
}
const getUser = `-- name: GetUser :one
SELECT
id, email, password, salt, disabled, admin, reg_time
FROM
user
WHERE
id = ?
LIMIT
1
`
func (q *Queries) GetUser(ctx context.Context, id int64) (User, error) {
row := q.queryRow(ctx, q.getUserStmt, getUser, id)
var i User
err := row.Scan(
&i.ID,
&i.Email,
&i.Password,
&i.Salt,
&i.Disabled,
&i.Admin,
&i.RegTime,
)
return i, err
}
const listUser = `-- name: ListUser :many
SELECT
id, email, password, salt, disabled, admin, reg_time
FROM
user
ORDER BY
reg_time
`
func (q *Queries) ListUser(ctx context.Context) ([]User, error) {
rows, err := q.query(ctx, q.listUserStmt, listUser)
if err != nil {
return nil, err
}
defer rows.Close()
var items []User
for rows.Next() {
var i User
if err := rows.Scan(
&i.ID,
&i.Email,
&i.Password,
&i.Salt,
&i.Disabled,
&i.Admin,
&i.RegTime,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}

37
db/mysql/sql/query.sql Normal file
View File

@ -0,0 +1,37 @@
-- name: GetUser :one
SELECT
*
FROM
user
WHERE
id = ?
LIMIT
1;
-- name: ListUser :many
SELECT
*
FROM
user
ORDER BY
reg_time;
-- name: CreateUser :execresult
INSERT INTO
user (
id,
email,
password,
salt,
disabled,
admin,
reg_time
)
VALUES
(?, ?, ?, ?, ?, ?, ?);
-- name: DeleteUser :exec
DELETE FROM
user
WHERE
id = ?;

33
db/mysql/sql/schema.sql Normal file
View File

@ -0,0 +1,33 @@
CREATE TABLE IF NOT EXISTS `user` (
id BIGINT PRIMARY KEY,
email VARCHAR(20) NOT NULL,
password text NOT NULL,
salt text NOT NULL,
state INT NOT NULL,
reg_time BIGINT NOT NULL
);
CREATE TABLE IF NOT EXISTS `skin` (
id BIGINT PRIMARY KEY,
-- 第一个上传的用户
user_id BIGINT NOT NULL,
skin_hash VARCHAR(50) NOT NULL,
`type` VARCHAR(10) NOT NULL,
variant VARCHAR(10) NOT NULL
);
CREATE TABLE IF NOT EXISTS `user_skin` (
user_id BIGINT PRIMARY KEY,
skin_id BIGINT NOT NULL
);
CREATE TABLE IF NOT EXISTS `user_token` (
user_id BIGINT PRIMARY KEY,
token_id INT NOT NULL
);
CREATE TABLE IF NOT EXISTS `user_profile` (
user_id BIGINT PRIMARY KEY,
name VARCHAR(20) NOT NULL,
uuid text NOT NULL
);

2
db/mysql/sqlc.go Normal file
View File

@ -0,0 +1,2 @@
//go:generate sqlc generate
package mysql

12
db/mysql/sqlc.yaml Normal file
View File

@ -0,0 +1,12 @@
version: 2
sql:
- engine: "mysql"
schema: "sql/schema.sql"
queries: "sql/query.sql"
gen:
go:
package: "mysql"
out: "."
emit_db_tags: true
emit_prepared_queries: true
emit_interface: true

19
go.mod Normal file
View File

@ -0,0 +1,19 @@
module github.com/xmdhs/authlib-skin
go 1.21.0
require (
github.com/go-playground/validator/v10 v10.15.3
github.com/julienschmidt/httprouter v1.3.0
)
require (
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
golang.org/x/crypto v0.7.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/text v0.8.0 // indirect
)

38
go.sum Normal file
View File

@ -0,0 +1,38 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.15.3 h1:S+sSpunYjNPDuXkWbK+x+bA7iXiW296KG4dL3X7xUZo=
github.com/go-playground/validator/v10 v10.15.3/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

18
handle/error.go Normal file
View File

@ -0,0 +1,18 @@
package handle
import (
"context"
"encoding/json"
"net/http"
"github.com/xmdhs/authlib-skin/model"
)
func handleError(ctx context.Context, w http.ResponseWriter, msg string, code int, httpcode int) {
w.WriteHeader(httpcode)
b, err := json.Marshal(model.API[any]{Code: code, Msg: msg, Data: nil})
if err != nil {
panic(err)
}
w.Write(b)
}

1
handle/user.go Normal file
View File

@ -0,0 +1 @@
package handle

View File

@ -0,0 +1,33 @@
package yggdrasil
import (
"encoding/json"
"log/slog"
"net/http"
"github.com/go-playground/validator/v10"
"github.com/julienschmidt/httprouter"
"github.com/xmdhs/authlib-skin/model/yggdrasil"
)
func Authenticate(l *slog.Logger, v *validator.Validate) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
cxt := r.Context()
jr := json.NewDecoder(r.Body)
var a yggdrasil.Authenticate
err := jr.Decode(&a)
if err != nil {
l.Info(err.Error())
handleYgError(cxt, w, yggdrasil.Error{ErrorMessage: err.Error()}, 400)
return
}
err = v.Struct(a)
if err != nil {
l.Info(err.Error())
handleYgError(cxt, w, yggdrasil.Error{ErrorMessage: err.Error()}, 400)
return
}
}
}

18
handle/yggdrasil/error.go Normal file
View File

@ -0,0 +1,18 @@
package yggdrasil
import (
"context"
"encoding/json"
"net/http"
"github.com/xmdhs/authlib-skin/model/yggdrasil"
)
func handleYgError(ctx context.Context, w http.ResponseWriter, e yggdrasil.Error, httpcode int) {
w.WriteHeader(httpcode)
b, err := json.Marshal(e)
if err != nil {
panic(err)
}
w.Write(b)
}

5
model/const.go Normal file
View File

@ -0,0 +1,5 @@
package model
const (
OK = 0
)

7
model/model.go Normal file
View File

@ -0,0 +1,7 @@
package model
type API[T any] struct {
Code int `json:"code"`
Data T `json:"data"`
Msg string `json:"msg"`
}

18
model/yggdrasil/model.go Normal file
View File

@ -0,0 +1,18 @@
package yggdrasil
type Authenticate struct {
Agent struct {
Name string `json:"name" validate:"required,eq=Minecraft"`
Version int `json:"version" validate:"required,eq=1"`
} `json:"agent"`
ClientToken string `json:"clientToken"`
Password string `json:"password" validate:"required"`
RequestUser bool `json:"requestUser"`
Username string `json:"username" validate:"required"`
}
type Error struct {
Cause string `json:"cause,omitempty"`
Error string `json:"error,omitempty"`
ErrorMessage string `json:"errorMessage,omitempty"`
}

20
server/server.go Normal file
View File

@ -0,0 +1,20 @@
package server
import (
"net/http"
"github.com/julienschmidt/httprouter"
)
func NewYggdrasil(r *httprouter.Router) error {
r.POST("/api/authserver/authenticate", nil)
return nil
}
func warpCtJSON(handle httprouter.Handle) httprouter.Handle {
return func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
handle(w, r, p)
}
}