-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a172ca0
commit 60c3c88
Showing
16 changed files
with
751 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
package server | ||
|
||
import ( | ||
"net/http" | ||
"polaris/db" | ||
"polaris/log" | ||
"polaris/pkg/utils" | ||
"strings" | ||
"time" | ||
|
||
"github.com/gin-gonic/gin" | ||
"github.com/golang-jwt/jwt/v5" | ||
"github.com/pkg/errors" | ||
) | ||
|
||
func (s *Server) isAuthEnabled() bool { | ||
authEnabled := s.db.GetSetting(db.SettingAuthEnabled) | ||
return authEnabled == "true" | ||
} | ||
|
||
func (s *Server) authModdleware(c *gin.Context) { | ||
if !s.isAuthEnabled() { | ||
c.Next() | ||
return | ||
} | ||
|
||
auth := c.GetHeader("Authorization") | ||
if auth == "" { | ||
c.AbortWithStatus(http.StatusForbidden) | ||
return | ||
} | ||
auth = strings.TrimPrefix(auth, "Bearer ") | ||
log.Infof("current token: %v", auth) | ||
token, err := jwt.ParseWithClaims(auth, &jwt.RegisteredClaims{}, func(t *jwt.Token) (interface{}, error) { | ||
return []byte(secretKey), nil | ||
}) | ||
if err != nil { | ||
log.Errorf("parse token error: %v", err) | ||
c.AbortWithStatus(http.StatusForbidden) | ||
return | ||
} | ||
if !token.Valid { | ||
log.Errorf("token is not valid: %v", auth) | ||
c.AbortWithStatus(http.StatusForbidden) | ||
return | ||
} | ||
claim := token.Claims.(*jwt.RegisteredClaims) | ||
|
||
if time.Until(claim.ExpiresAt.Time) <= 0 { | ||
log.Infof("token is no longer valid: %s", auth) | ||
c.AbortWithStatus(http.StatusForbidden) | ||
return | ||
} | ||
c.Next() | ||
|
||
} | ||
|
||
type LoginIn struct { | ||
User string `json:"user"` | ||
Password string `json:"password"` | ||
} | ||
|
||
const secretKey = "r1OF7nhpNjnYiGKtTLuKEVq7YznzT" | ||
|
||
func (s *Server) Login(c *gin.Context) (interface{}, error) { | ||
var in LoginIn | ||
|
||
if err := c.ShouldBindJSON(&in); err != nil { | ||
return nil, errors.Wrap(err, "bind json") | ||
} | ||
|
||
if !s.isAuthEnabled() { | ||
return nil, nil | ||
} | ||
|
||
user := s.db.GetSetting(db.SettingUsername) | ||
if user != in.User { | ||
return nil, errors.New("login fail") | ||
} | ||
password := s.db.GetSetting(db.SettingPassword) | ||
if !utils.VerifyPassword(in.Password, password) { | ||
return nil, errors.New("login fail") | ||
} | ||
|
||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.RegisteredClaims{ | ||
Issuer: "system", | ||
Subject: in.User, | ||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(7 * 24 * time.Hour)), | ||
IssuedAt: jwt.NewNumericDate(time.Now()), | ||
NotBefore: jwt.NewNumericDate(time.Now()), | ||
}) | ||
sig, err := token.SignedString([]byte(secretKey)) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "sign") | ||
} | ||
return gin.H{ | ||
"token": sig, | ||
}, nil | ||
} | ||
|
||
type EnableAuthIn struct { | ||
Enable bool `json:"enable"` | ||
User string `json:"user"` | ||
Password string `json:"password"` | ||
} | ||
|
||
func (s *Server) EnableAuth(c *gin.Context) (interface{}, error) { | ||
var in EnableAuthIn | ||
if err := c.ShouldBindJSON(&in); err != nil { | ||
return nil, errors.Wrap(err, "bind json") | ||
} | ||
|
||
if in.Enable && (in.User == "" || in.Password == "") { | ||
return nil, errors.New("user password should not empty") | ||
} | ||
if !in.Enable { | ||
log.Infof("disable auth") | ||
s.db.SetSetting(db.SettingAuthEnabled, "false") | ||
} else { | ||
log.Info("enable auth") | ||
s.db.SetSetting(db.SettingAuthEnabled, "true") | ||
s.db.SetSetting(db.SettingUsername, in.User) | ||
|
||
hash, err := utils.HashPassword(in.Password) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "hash password") | ||
} | ||
s.db.SetSetting(db.SettingPassword, hash) | ||
} | ||
return "success", nil | ||
} | ||
|
||
func (s *Server) GetAuthSetting(c *gin.Context) (interface{}, error) { | ||
enabled := s.db.GetSetting(db.SettingAuthEnabled) | ||
user := s.db.GetSetting(db.SettingUsername) | ||
|
||
return EnableAuthIn{ | ||
Enable: enabled == "true", | ||
User: user, | ||
}, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter/scheduler.dart' show timeDilation; | ||
import 'package:flutter_login/flutter_login.dart'; | ||
import 'package:flutter_riverpod/flutter_riverpod.dart'; | ||
import 'package:go_router/go_router.dart'; | ||
import 'package:quiver/strings.dart'; | ||
import 'package:ui/providers/login.dart'; | ||
import 'package:ui/weclome.dart'; | ||
|
||
class LoginScreen extends ConsumerWidget { | ||
static const route = '/login'; | ||
|
||
const LoginScreen({super.key}); | ||
|
||
Duration get loginTime => Duration(milliseconds: timeDilation.ceil() * 2250); | ||
|
||
|
||
Future<String?> _recoverPassword(String name) { | ||
return Future.delayed(loginTime).then((_) { | ||
return null; | ||
}); | ||
} | ||
|
||
|
||
@override | ||
Widget build(BuildContext context, WidgetRef ref) { | ||
return FlutterLogin( | ||
title: 'Polaris', | ||
onLogin: (data) { | ||
ref.read(authSettingProvider.notifier).login(data.name, data.password); | ||
}, | ||
onSubmitAnimationCompleted: () { | ||
context.go(WelcomePage.route); | ||
}, | ||
onRecoverPassword: _recoverPassword, | ||
userValidator: (value) => isBlank(value)? "不能为空":null, | ||
userType: LoginUserType.name, | ||
hideForgotPasswordButton: true, | ||
messages: LoginMessages( | ||
userHint: '用户名', | ||
passwordHint: '密码', | ||
loginButton: '登录', | ||
), | ||
); | ||
} | ||
} | ||
|
||
class IntroWidget extends StatelessWidget { | ||
const IntroWidget({super.key}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return const Column( | ||
children: [ | ||
Text.rich( | ||
TextSpan( | ||
children: [ | ||
TextSpan( | ||
text: "You are trying to login/sign up on server hosted on ", | ||
), | ||
TextSpan( | ||
text: "example.com", | ||
style: TextStyle(fontWeight: FontWeight.bold), | ||
), | ||
], | ||
), | ||
textAlign: TextAlign.justify, | ||
), | ||
Row( | ||
children: <Widget>[ | ||
Expanded(child: Divider()), | ||
Padding( | ||
padding: EdgeInsets.all(8.0), | ||
child: Text("Authenticate"), | ||
), | ||
Expanded(child: Divider()), | ||
], | ||
), | ||
], | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.