Compare commits
7
Commits
1.6.7
...
v2-final-1.6.8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8df8dcce7 | ||
|
|
2bf8d3887e | ||
|
|
efe45f39e7 | ||
|
|
336a1f353f | ||
|
|
a19080ef39 | ||
|
|
2bddc6a224 | ||
|
|
3bf5d8290e |
@@ -80,10 +80,27 @@ jobs:
|
||||
go-version: '1.25'
|
||||
cache-dependency-path: go.sum
|
||||
|
||||
- name: Cache Go build cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
# setup-go only caches modules (GOMODCACHE). This caches compiled
|
||||
# packages (GOCACHE) so the cgo/WebKit compile goes incremental.
|
||||
# restore-keys gives a close cache instead of a cold one when
|
||||
# go.sum changes. First run after adding this still compiles cold
|
||||
# (it saves); the payoff shows from the second run on.
|
||||
path: ~/.cache/go-build
|
||||
key: go-build-1.25-${{ runner.os }}-${{ hashFiles('go.sum') }}
|
||||
restore-keys: |
|
||||
go-build-1.25-${{ runner.os }}-
|
||||
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
# Caches npm's download cache keyed on the frontend lockfile, so
|
||||
# the `npm install` inside `wails build` stops fetching cold.
|
||||
cache: 'npm'
|
||||
cache-dependency-path: frontend/package-lock.json
|
||||
|
||||
- name: Install Wails Linux build dependencies
|
||||
run: |
|
||||
@@ -94,11 +111,23 @@ jobs:
|
||||
libgtk-3-dev libwebkit2gtk-4.1-dev \
|
||||
jq
|
||||
|
||||
- name: Cache Wails CLI
|
||||
uses: actions/cache@v4
|
||||
id: wails-cli
|
||||
with:
|
||||
# The compiled CLI binary. Bump the key whenever the @version pin
|
||||
# below changes, or the old CLI will be silently reused.
|
||||
path: ~/go/bin/wails
|
||||
key: wails-v2.15.0-${{ runner.os }}
|
||||
|
||||
- name: Install Wails CLI
|
||||
if: steps.wails-cli.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
set -euo pipefail
|
||||
go install github.com/wailsapp/wails/v2/cmd/wails@v2.15.0
|
||||
echo "${HOME}/go/bin" >> "${GITHUB_PATH}"
|
||||
|
||||
- name: Add Go bin to PATH
|
||||
run: echo "${HOME}/go/bin" >> "${GITHUB_PATH}"
|
||||
|
||||
- name: Write environment.go from secrets
|
||||
env:
|
||||
|
||||
+4
-1
@@ -23,10 +23,13 @@ go.work
|
||||
|
||||
# ---> Wails
|
||||
build/bin
|
||||
.task/
|
||||
node_modules
|
||||
frontend/dist
|
||||
package.json.md5
|
||||
package-lock.json
|
||||
# Root-level lockfile only: the frontend lockfile IS tracked so CI installs
|
||||
# are reproducible and setup-node's npm cache has something to hash.
|
||||
/package-lock.json
|
||||
.idea
|
||||
.env
|
||||
environment.go
|
||||
|
||||
+55
-20
@@ -19,18 +19,48 @@ import (
|
||||
|
||||
var aniListJwt AniListJWT
|
||||
|
||||
var aniRing, _ = keyring.Open(keyring.Config{
|
||||
var aniRing keyring.Keyring
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
aniRing, err = keyring.Open(keyring.Config{
|
||||
ServiceName: "AniTrack",
|
||||
KeychainName: "AniTrack",
|
||||
KeychainSynchronizable: false,
|
||||
KeychainTrustApplication: true,
|
||||
KeychainAccessibleWhenUnlocked: true,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("anilist: secure storage unavailable: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func aniRingReady() bool {
|
||||
if aniRing == nil {
|
||||
log.Println("anilist: secure storage unavailable")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func aniRingSet(key string, data []byte) error {
|
||||
if !aniRingReady() {
|
||||
return errors.New("anilist: secure storage unavailable")
|
||||
}
|
||||
if err := aniRing.Set(keyring.Item{Key: key, Data: data}); err != nil {
|
||||
log.Printf("anilist: save %s failed: %s", key, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var aniCtxShutdown, aniCancel = context.WithCancel(context.Background())
|
||||
|
||||
func (a *App) CheckIfAniListLoggedIn() bool {
|
||||
if (AniListJWT{} == aniListJwt) {
|
||||
if !aniRingReady() {
|
||||
return false
|
||||
}
|
||||
tokenType, tokenErr := aniRing.Get("anilistTokenType")
|
||||
expiresIn, expiresInErr := aniRing.Get("anilistTokenExpiresIn")
|
||||
refreshToken, refreshTokenErr := aniRing.Get("anilistRefreshToken")
|
||||
@@ -38,10 +68,15 @@ func (a *App) CheckIfAniListLoggedIn() bool {
|
||||
if (tokenErr != nil || expiresInErr != nil || refreshTokenErr != nil || accessTokenErr != nil) || len(accessToken.Data) == 0 {
|
||||
return false
|
||||
} else {
|
||||
var expiresInConvertErr error
|
||||
aniListJwt.TokenType = string(tokenType.Data)
|
||||
aniListJwt.AccessToken = string(accessToken.Data)
|
||||
aniListJwt.RefreshToken = string(refreshToken.Data)
|
||||
aniListJwt.ExpiresIn, _ = strconv.Atoi(string(expiresIn.Data))
|
||||
aniListJwt.ExpiresIn, expiresInConvertErr = strconv.Atoi(string(expiresIn.Data))
|
||||
if expiresInConvertErr != nil {
|
||||
log.Printf("anilist: invalid expiresIn %q: %s", string(expiresIn.Data), expiresInConvertErr)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
@@ -51,6 +86,10 @@ func (a *App) CheckIfAniListLoggedIn() bool {
|
||||
|
||||
func (a *App) AniListLogin() {
|
||||
if (AniListJWT{} == aniListJwt) {
|
||||
if !aniRingReady() {
|
||||
log.Println("anilist: cannot check login, secure storage unavailable")
|
||||
return
|
||||
}
|
||||
tokenType, tokenErr := aniRing.Get("anilistTokenType")
|
||||
expiresIn, expiresInErr := aniRing.Get("anilistTokenExpiresIn")
|
||||
refreshToken, refreshTokenErr := aniRing.Get("anilistRefreshToken")
|
||||
@@ -64,10 +103,14 @@ func (a *App) AniListLogin() {
|
||||
a.handleAniListCallback(serverDone)
|
||||
serverDone.Wait()
|
||||
} else {
|
||||
var expiresInConvertErr error
|
||||
aniListJwt.TokenType = string(tokenType.Data)
|
||||
aniListJwt.AccessToken = string(accessToken.Data)
|
||||
aniListJwt.RefreshToken = string(refreshToken.Data)
|
||||
aniListJwt.ExpiresIn, _ = strconv.Atoi(string(expiresIn.Data))
|
||||
aniListJwt.ExpiresIn, expiresInConvertErr = strconv.Atoi(string(expiresIn.Data))
|
||||
if expiresInConvertErr != nil {
|
||||
log.Printf("anilist: invalid expiresIn %q: %s", string(expiresIn.Data), expiresInConvertErr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -85,22 +128,10 @@ func (a *App) handleAniListCallback(wg *sync.WaitGroup) {
|
||||
content := r.FormValue("code")
|
||||
if content != "" {
|
||||
aniListJwt = getAniListAuthorizationToken(content)
|
||||
_ = aniRing.Set(keyring.Item{
|
||||
Key: "anilistTokenType",
|
||||
Data: []byte(aniListJwt.TokenType),
|
||||
})
|
||||
_ = aniRing.Set(keyring.Item{
|
||||
Key: "anilistTokenExpiresIn",
|
||||
Data: []byte(strconv.Itoa(aniListJwt.ExpiresIn)),
|
||||
})
|
||||
_ = aniRing.Set(keyring.Item{
|
||||
Key: "anilistAccessToken",
|
||||
Data: []byte(aniListJwt.AccessToken),
|
||||
})
|
||||
_ = aniRing.Set(keyring.Item{
|
||||
Key: "anilistRefreshToken",
|
||||
Data: []byte(aniListJwt.RefreshToken),
|
||||
})
|
||||
_ = aniRingSet("anilistTokenType", []byte(aniListJwt.TokenType))
|
||||
_ = aniRingSet("anilistTokenExpiresIn", []byte(strconv.Itoa(aniListJwt.ExpiresIn)))
|
||||
_ = aniRingSet("anilistAccessToken", []byte(aniListJwt.AccessToken))
|
||||
_ = aniRingSet("anilistRefreshToken", []byte(aniListJwt.RefreshToken))
|
||||
_, err := runtime.MessageDialog(*wailsContext, runtime.MessageDialogOptions{
|
||||
Title: "AniList Authorization",
|
||||
Message: "It is now safe to close your browser tab",
|
||||
@@ -208,12 +239,16 @@ func (a *App) GetAniListLoggedInUser() AniListUser {
|
||||
|
||||
func (a *App) LogoutAniList() string {
|
||||
if (AniListJWT{} != aniListJwt) {
|
||||
if !aniRingReady() {
|
||||
aniListJwt = AniListJWT{}
|
||||
return "AniList Logged Out Successfully"
|
||||
}
|
||||
typeErr := aniRing.Remove("anilistTokenType")
|
||||
expiresInErr := aniRing.Remove("anilistTokenExpiresIn")
|
||||
accessTokenErr := aniRing.Remove("anilistAccessToken")
|
||||
refreshTokenErr := aniRing.Remove("anilistRefreshToken")
|
||||
if typeErr != nil || expiresInErr != nil || accessTokenErr != nil || refreshTokenErr != nil {
|
||||
fmt.Println("AniList Logout Failed")
|
||||
log.Printf("anilist: logout cleanup failed (type=%v expires=%v access=%v refresh=%v)", typeErr, expiresInErr, accessTokenErr, refreshTokenErr)
|
||||
}
|
||||
aniListJwt = AniListJWT{}
|
||||
}
|
||||
|
||||
+51
-36
@@ -23,13 +23,40 @@ import (
|
||||
|
||||
var myAnimeListJwt MyAnimeListJWT
|
||||
|
||||
var myAnimeListRing, _ = keyring.Open(keyring.Config{
|
||||
var myAnimeListRing keyring.Keyring
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
myAnimeListRing, err = keyring.Open(keyring.Config{
|
||||
ServiceName: "AniTrack",
|
||||
KeychainName: "AniTrack",
|
||||
KeychainSynchronizable: false,
|
||||
KeychainTrustApplication: true,
|
||||
KeychainAccessibleWhenUnlocked: true,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("mal: secure storage unavailable: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func malRingReady() bool {
|
||||
if myAnimeListRing == nil {
|
||||
log.Println("mal: secure storage unavailable")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func malRingSet(key string, data []byte) error {
|
||||
if !malRingReady() {
|
||||
return errors.New("mal: secure storage unavailable")
|
||||
}
|
||||
if err := myAnimeListRing.Set(keyring.Item{Key: key, Data: data}); err != nil {
|
||||
log.Printf("mal: save %s failed: %s", key, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var myAnimeListCtxShutdown, myAnimeListCancel = context.WithCancel(context.Background())
|
||||
|
||||
@@ -72,6 +99,9 @@ func (v *CodeVerifier) CodeChallengeS256() string {
|
||||
|
||||
func (a *App) CheckIfMyAnimeListLoggedIn() bool {
|
||||
if (MyAnimeListJWT{} == myAnimeListJwt) {
|
||||
if !malRingReady() {
|
||||
return false
|
||||
}
|
||||
tokenType, tokenErr := myAnimeListRing.Get("MyAnimeListTokenType")
|
||||
expiresIn, expiresInErr := myAnimeListRing.Get("MyAnimeListExpiresIn")
|
||||
accessToken, accessTokenErr := myAnimeListRing.Get("MyAnimeListAccessToken")
|
||||
@@ -83,7 +113,8 @@ func (a *App) CheckIfMyAnimeListLoggedIn() bool {
|
||||
myAnimeListJwt.TokenType = string(tokenType.Data)
|
||||
myAnimeListJwt.ExpiresIn, expiresInConvertErr = strconv.Atoi(string(expiresIn.Data))
|
||||
if expiresInConvertErr != nil {
|
||||
fmt.Println("unable to convert string to int")
|
||||
log.Printf("mal: invalid expiresIn %q: %s", string(expiresIn.Data), expiresInConvertErr)
|
||||
return false
|
||||
}
|
||||
myAnimeListJwt.AccessToken = string(accessToken.Data)
|
||||
myAnimeListJwt.RefreshToken = string(refreshToken.Data)
|
||||
@@ -97,6 +128,10 @@ func (a *App) CheckIfMyAnimeListLoggedIn() bool {
|
||||
func (a *App) MyAnimeListLogin() {
|
||||
if !a.CheckIfMyAnimeListLoggedIn() {
|
||||
fmt.Println("check logged in function failed")
|
||||
if !malRingReady() {
|
||||
log.Println("mal: cannot check login, secure storage unavailable")
|
||||
return
|
||||
}
|
||||
tokenType, tokenErr := myAnimeListRing.Get("MyAnimeListTokenType")
|
||||
expiresIn, expiresInErr := myAnimeListRing.Get("MyAnimeListExpiresIn")
|
||||
accessToken, accessTokenErr := myAnimeListRing.Get("MyAnimeListAccessToken")
|
||||
@@ -114,7 +149,7 @@ func (a *App) MyAnimeListLogin() {
|
||||
myAnimeListJwt.TokenType = string(tokenType.Data)
|
||||
myAnimeListJwt.ExpiresIn, expiresInConvertErr = strconv.Atoi(string(expiresIn.Data))
|
||||
if expiresInConvertErr != nil {
|
||||
fmt.Println("unable to convert string to int in Login function")
|
||||
log.Printf("mal: invalid expiresIn %q: %s", string(expiresIn.Data), expiresInConvertErr)
|
||||
}
|
||||
myAnimeListJwt.AccessToken = string(accessToken.Data)
|
||||
myAnimeListJwt.RefreshToken = string(refreshToken.Data)
|
||||
@@ -136,22 +171,10 @@ func (a *App) handleMyAnimeListCallback(wg *sync.WaitGroup, verifier *CodeVerifi
|
||||
|
||||
if content != "" {
|
||||
myAnimeListJwt = getMyAnimeListAuthorizationToken(content, verifier)
|
||||
_ = myAnimeListRing.Set(keyring.Item{
|
||||
Key: "MyAnimeListTokenType",
|
||||
Data: []byte(myAnimeListJwt.TokenType),
|
||||
})
|
||||
_ = myAnimeListRing.Set(keyring.Item{
|
||||
Key: "MyAnimeListExpiresIn",
|
||||
Data: []byte(strconv.Itoa(myAnimeListJwt.ExpiresIn)),
|
||||
})
|
||||
_ = myAnimeListRing.Set(keyring.Item{
|
||||
Key: "MyAnimeListAccessToken",
|
||||
Data: []byte(myAnimeListJwt.AccessToken),
|
||||
})
|
||||
_ = myAnimeListRing.Set(keyring.Item{
|
||||
Key: "MyAnimeListRefreshToken",
|
||||
Data: []byte(myAnimeListJwt.RefreshToken),
|
||||
})
|
||||
_ = malRingSet("MyAnimeListTokenType", []byte(myAnimeListJwt.TokenType))
|
||||
_ = malRingSet("MyAnimeListExpiresIn", []byte(strconv.Itoa(myAnimeListJwt.ExpiresIn)))
|
||||
_ = malRingSet("MyAnimeListAccessToken", []byte(myAnimeListJwt.AccessToken))
|
||||
_ = malRingSet("MyAnimeListRefreshToken", []byte(myAnimeListJwt.RefreshToken))
|
||||
_, err := runtime.MessageDialog(*wailsContext, runtime.MessageDialogOptions{
|
||||
Title: "MyAnimeList Authorization",
|
||||
Message: "It is now safe to close your browser tab",
|
||||
@@ -292,22 +315,10 @@ func refreshMyAnimeListAuthorizationToken() bool {
|
||||
|
||||
myAnimeListJwt = refreshed
|
||||
|
||||
_ = myAnimeListRing.Set(keyring.Item{
|
||||
Key: "MyAnimeListTokenType",
|
||||
Data: []byte(myAnimeListJwt.TokenType),
|
||||
})
|
||||
_ = myAnimeListRing.Set(keyring.Item{
|
||||
Key: "MyAnimeListExpiresIn",
|
||||
Data: []byte(strconv.Itoa(myAnimeListJwt.ExpiresIn)),
|
||||
})
|
||||
_ = myAnimeListRing.Set(keyring.Item{
|
||||
Key: "MyAnimeListAccessToken",
|
||||
Data: []byte(myAnimeListJwt.AccessToken),
|
||||
})
|
||||
_ = myAnimeListRing.Set(keyring.Item{
|
||||
Key: "MyAnimeListRefreshToken",
|
||||
Data: []byte(myAnimeListJwt.RefreshToken),
|
||||
})
|
||||
_ = malRingSet("MyAnimeListTokenType", []byte(myAnimeListJwt.TokenType))
|
||||
_ = malRingSet("MyAnimeListExpiresIn", []byte(strconv.Itoa(myAnimeListJwt.ExpiresIn)))
|
||||
_ = malRingSet("MyAnimeListAccessToken", []byte(myAnimeListJwt.AccessToken))
|
||||
_ = malRingSet("MyAnimeListRefreshToken", []byte(myAnimeListJwt.RefreshToken))
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -367,12 +378,16 @@ func createUser() MyAnimeListUser {
|
||||
|
||||
func (a *App) LogoutMyAnimeList() string {
|
||||
if (MyAnimeListJWT{} != myAnimeListJwt) {
|
||||
if !malRingReady() {
|
||||
myAnimeListJwt = MyAnimeListJWT{}
|
||||
return "MAL Logged Out Successfully"
|
||||
}
|
||||
typeErr := myAnimeListRing.Remove("MyAnimeListTokenType")
|
||||
expiresInErr := myAnimeListRing.Remove("MyAnimeListExpiresIn")
|
||||
accessTokenErr := myAnimeListRing.Remove("MyAnimeListAccessToken")
|
||||
refreshTokenErr := myAnimeListRing.Remove("MyAnimeListRefreshToken")
|
||||
if typeErr != nil || expiresInErr != nil || accessTokenErr != nil || refreshTokenErr != nil {
|
||||
fmt.Println("MAL Logout Failed")
|
||||
log.Printf("mal: logout cleanup failed (type=%v expires=%v access=%v refresh=%v)", typeErr, expiresInErr, accessTokenErr, refreshTokenErr)
|
||||
}
|
||||
myAnimeListJwt = MyAnimeListJWT{}
|
||||
}
|
||||
|
||||
+43
-14
@@ -17,18 +17,48 @@ import (
|
||||
|
||||
var simklJwt SimklJWT
|
||||
|
||||
var simklRing, _ = keyring.Open(keyring.Config{
|
||||
var simklRing keyring.Keyring
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
simklRing, err = keyring.Open(keyring.Config{
|
||||
ServiceName: "AniTrack",
|
||||
KeychainName: "AniTrack",
|
||||
KeychainSynchronizable: false,
|
||||
KeychainTrustApplication: true,
|
||||
KeychainAccessibleWhenUnlocked: true,
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("simkl: secure storage unavailable: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func simklRingReady() bool {
|
||||
if simklRing == nil {
|
||||
log.Println("simkl: secure storage unavailable")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func simklRingSet(key string, data []byte) error {
|
||||
if !simklRingReady() {
|
||||
return errors.New("simkl: secure storage unavailable")
|
||||
}
|
||||
if err := simklRing.Set(keyring.Item{Key: key, Data: data}); err != nil {
|
||||
log.Printf("simkl: save %s failed: %s", key, err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var simklCtxShutdown, simklCancel = context.WithCancel(context.Background())
|
||||
|
||||
func (a *App) CheckIfSimklLoggedIn() bool {
|
||||
if (SimklJWT{} == simklJwt) {
|
||||
if !simklRingReady() {
|
||||
return false
|
||||
}
|
||||
tokenType, tokenTypeErr := simklRing.Get("SimklTokenType")
|
||||
accessToken, accessTokenErr := simklRing.Get("SimklAccessToken")
|
||||
scope, scopeErr := simklRing.Get("SimklScope")
|
||||
@@ -47,6 +77,10 @@ func (a *App) CheckIfSimklLoggedIn() bool {
|
||||
|
||||
func (a *App) SimklLogin() {
|
||||
if !a.CheckIfSimklLoggedIn() {
|
||||
if !simklRingReady() {
|
||||
log.Println("simkl: cannot check login, secure storage unavailable")
|
||||
return
|
||||
}
|
||||
tokenType, tokenTypeErr := simklRing.Get("SimklTokenType")
|
||||
accessToken, accessTokenErr := simklRing.Get("SimklAccessToken")
|
||||
scope, scopeErr := simklRing.Get("SimklScope")
|
||||
@@ -80,18 +114,9 @@ func (a *App) handleSimklCallback(wg *sync.WaitGroup) {
|
||||
|
||||
if content != "" {
|
||||
simklJwt = getSimklAuthorizationToken(content)
|
||||
_ = simklRing.Set(keyring.Item{
|
||||
Key: "SimklTokenType",
|
||||
Data: []byte(simklJwt.TokenType),
|
||||
})
|
||||
_ = simklRing.Set(keyring.Item{
|
||||
Key: "SimklAccessToken",
|
||||
Data: []byte(simklJwt.AccessToken),
|
||||
})
|
||||
_ = simklRing.Set(keyring.Item{
|
||||
Key: "SimklScope",
|
||||
Data: []byte(simklJwt.Scope),
|
||||
})
|
||||
_ = simklRingSet("SimklTokenType", []byte(simklJwt.TokenType))
|
||||
_ = simklRingSet("SimklAccessToken", []byte(simklJwt.AccessToken))
|
||||
_ = simklRingSet("SimklScope", []byte(simklJwt.Scope))
|
||||
_, err := runtime.MessageDialog(*wailsContext, runtime.MessageDialogOptions{
|
||||
Title: "Simkl Authorization",
|
||||
Message: "It is now safe to close your browser tab",
|
||||
@@ -218,12 +243,16 @@ func (a *App) GetSimklLoggedInUser() SimklUser {
|
||||
|
||||
func (a *App) LogoutSimkl() string {
|
||||
if (SimklJWT{} != simklJwt) {
|
||||
if !simklRingReady() {
|
||||
simklJwt = SimklJWT{}
|
||||
return "Simkl Logged Out Successfully"
|
||||
}
|
||||
tokenTypeErr := simklRing.Remove("SimklTokenType")
|
||||
accessTokenErr := simklRing.Remove("SimklAccessToken")
|
||||
scopeErr := simklRing.Remove("SimklScope")
|
||||
|
||||
if tokenTypeErr != nil || accessTokenErr != nil || scopeErr != nil {
|
||||
fmt.Println("Simkl Logout Failed")
|
||||
log.Printf("simkl: logout cleanup failed (type=%v access=%v scope=%v)", tokenTypeErr, accessTokenErr, scopeErr)
|
||||
}
|
||||
simklJwt = SimklJWT{}
|
||||
}
|
||||
|
||||
Generated
+2717
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -12,6 +12,6 @@
|
||||
},
|
||||
"info": {
|
||||
"productName": "AniTrack",
|
||||
"productVersion": "1.6.7"
|
||||
"productVersion": "1.6.8"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user