Compare commits

...

18 Commits

Author SHA1 Message Date
Easy b8fa724a9a
Update README.md 2024-02-26 21:46:50 +08:00
Easy 4ce68572b9
Update README.md 2023-12-29 12:33:49 +08:00
Easy 16aec6c468
Update README.md 2023-12-29 12:32:56 +08:00
Easy bfadc52fef 更新证书 2023-12-16 13:15:19 +08:00
Easy d7f3279458
Update README.md
remove core image
2023-11-10 18:11:31 +08:00
Easy f5841403c7
Update docker-compose.serverless.yml 2023-11-10 18:08:46 +08:00
Easy be51654558
Update README.md 2023-10-13 10:54:37 +08:00
Easy aa9a2a9dfa
Update README.md 2023-10-13 10:54:12 +08:00
Easy 1a9ad9e351 update 2023-02-02 23:27:03 +08:00
Easy 19011afdd0 更新推送证书 2023-01-15 16:24:03 +08:00
Easy f9779893ec
Update README.md 2022-12-20 08:26:35 +08:00
Easy 09acc7955e
Merge pull request #159 from abgelehnt/main
添加Rust SDK引用
2022-11-23 20:12:34 +08:00
Chi 6053cf624a
添加Rust SDK引用 2022-11-23 19:25:29 +08:00
Easy d15892727a
Update README.md 2022-09-24 11:00:22 +08:00
Easy b5e6605328
隐藏自架版mysql端口,避免和宿主机冲突 2022-09-21 11:25:41 +08:00
Easy 8e5292acfb
Merge pull request #148 from Hext123/main
获取用户信息时增加了simple_token字段,存下来,token过期以后调用 /login/simple_token 重新获得新的认证token
2022-09-14 00:38:19 +08:00
hext ed61f49eca 获取用户信息时增加了simple_token字段,存下来,token过期以后调用 /login/simple_token 重新获得新的认证token 2022-09-14 00:14:19 +08:00
Easy 6927a94860 添加SimpleToken的API实现和文档 2022-09-06 01:02:53 +08:00
18 changed files with 336 additions and 37 deletions

View File

@ -1,9 +1,11 @@
> ⚠️ 目前官方架设的Android版本因接口权限停止无法使用[详情请点击](https://github.com/easychen/pushdeer/issues/150)
> ⚠️ 自架版服务器端需每年更新推送证书,如果之前架设的服务突然无法收到推送,请尝试拉取部署最新代码,或者[手动更新证书](https://github.com/easychen/pushdeer/tree/main/push)
PushDeer是一个可以自行架设的无APP推送服务同时也为因为某些原因无法使用无APP推送方案的同学提供有APP/自制设备方案。
[🐙🐱 GitHub仓库](https://github.com/easychen/pushdeer) [🔮 中国大陆镜像仓库@Gitee](https://gitee.com/easychen/pushdeer)
> [🤖 Android自架版求开发者参与](doc/Android%E7%89%88self-hosted%E7%9A%84%E8%AE%BE%E8%AE%A1%E5%92%8C%E5%AE%9E%E7%8E%B0.md)
本项目已经实现的方案/端包括:
- 无APP方案
@ -97,6 +99,7 @@ https://api2.pushdeer.com/message/push?pushkey=<key>&text=标题&desp=<markdown>
- [Python SDK](https://github.com/gaoliang/pypushdeer) by [Gao Liang](https://github.com/gaoliang)
- [Go SDK](https://github.com/Luoxin/go-pushdeer-sdk) by [Luoxin](https://github.com/Luoxin)
- [Rust SDK](https://github.com/abgelehnt/rupushdeer) by [Chi](https://github.com/abgelehnt)
PHP函数
@ -158,20 +161,19 @@ function pushdeer_send($text, $desp = '', $type='text', $key = '[PUSHKEY]')
然后运行以下代码:
(大陆服务器使用)
```
git clone https://gitee.com/easychen/pushdeer.git
cd pushdeer
docker-compose -f docker-compose.self-hosted.yml up --build -d
```
(海外服务器使用)
```
git clone https://github.com/easychen/pushdeer.git
cd pushdeer
docker-compose -f docker-compose.self-hosted.yml up --build -d
```
如果你的服务器连接GitHub有困难可以使用Gitee的代码但需要核对是否为最新版本有可能没同步
```
git clone https://gitee.com/easychen/pushdeer.git
cd pushdeer
docker-compose -f docker-compose.self-hosted.yml up --build -d
```
> 如提示docker服务未安装/找不到/未启动,可在 docker-compose 前加 sudo 再试
等待初始化完成后,访问 `$AAA(需替换为服务器端IP或域名):8800`,看到扫码提示和图片则说明容器已经启动。
@ -180,6 +182,7 @@ docker-compose -f docker-compose.self-hosted.yml up --build -d
如果您在部署中遇到问题,可按[调试文档](/doc/调试文档.md)定位并发现错误信息。
<!--
#### 单一容器部署方案
对于很多不能运行docker-compose的容器环境可以直接使用 pushdeer 镜像。该镜像中已经包含了 redis 服务,但需要通过环境变量指定数据库等信息:
@ -189,6 +192,7 @@ docker run -e DB_DATABASE=* -e DB_HOST=* -e DB_PORT=*28740* -e DB_USERNAME=* -e
```
请将上述命令中的`*`替换为对应的数据库信息。
-->
### 使用自架版客户端
@ -419,6 +423,38 @@ type 为 image 时text 中为要发送图片的URL。
|-|-|-|
|token|认证token|
#### Simple token
> 为了方便客户端永久保持登入状态我们提供了一个永不失效的Token即 Simple token
##### 获取 Simple token
通过 上文中的「获得当前用户的基本信息」接口(`POST /user/info`) 得到
##### 通过 Simple token 登入
`POST /login/simple_token`
|参数|说明|备注|
|-|-|-|
|stoken|Simple token|
登入成功返回认证token。
##### 重置 Simple token
`POST /simple_token/regen`
|参数|说明|备注|
|-|-|-|
|token|认证token|
##### 清空 Simple token
`POST /simple_token/remove`
|参数|说明|备注|
|-|-|-|
|token|认证token|
[更详细的请求和返回值可以参考这里](doc/api/PushDeerOS.md)
@ -521,7 +557,7 @@ PushDeer主要面向以下三类用户
# 授权
本项目禁止商用(包括但不限于搭建后挂广告或售卖会员、打包后上架商店销售等),对非商业用途采用 GPLV2 授权
本项目禁止商用(包括但不限于搭建后挂广告或售卖会员、打包后上架商店销售等),在非商用的情况下遵循GPL v2当两者冲突时以非商用原则优先。
# 相关项目
@ -532,4 +568,4 @@ PushDeer主要面向以下三类用户
- [API的Go实现](https://github.com/iepngs/pushdeer-backend-go) by [iepngs](https://github.com/iepngs)
- [API的Node实现](https://github.com/xkrfer/pushdeer-node) by [DouDou](https://github.com/xkrfer)
- [浏览器插件](https://github.com/xkrfer/pushdeer-crx) by [DouDou](https://github.com/xkrfer)
- [Rust SDK](https://github.com/abgelehnt/rupushdeer) by [Chi](https://github.com/abgelehnt)

View File

@ -39,6 +39,8 @@ class PushDeerUserController extends Controller
$the_user['level'] = 1;
$pd_user = PushDeerUser::create($the_user);
$pd_user['simple_token'] = 'SP'.$pd_user['id'].'P'.md5(uniqid(rand(), true));
$pd_user->save();
}
// 将数据写到session
@ -47,6 +49,7 @@ class PushDeerUserController extends Controller
$_SESSION['name'] = $pd_user['name'];
$_SESSION['email'] = $pd_user['email'];
$_SESSION['level'] = $pd_user['level'];
$_SESSION['simple_token'] = $pd_user['simple_token'];
session_regenerate_id(true);
$token = session_id();
@ -56,6 +59,56 @@ class PushDeerUserController extends Controller
return send_error('id_token解析错误', ErrorCode('ARGS'));
}
public function loginBySimpleToken(Request $request)
{
$validated = $request->validate(
[
'stoken' => 'required|string',
]
);
if (!$pd_user = PushDeerUser::where('simple_token', $validated['stoken'])->get()->first()) {
return send_error('stoken无效', ErrorCode('ARGS'));
}
if ($pd_user['level']<1) {
return send_error('账号已被禁用', ErrorCode('ARGS'));
}
// 将数据写到session
session_start();
$_SESSION['uid'] = $pd_user['id'];
$_SESSION['name'] = $pd_user['name'];
$_SESSION['email'] = $pd_user['email'];
$_SESSION['level'] = $pd_user['level'];
session_regenerate_id(true);
$token = session_id();
return http_result(['token'=>$token]);
}
public function simpleTokenRegen(Request $request)
{
// get user by session
if (!$pd_user = PushDeerUser::where('id', $_SESSION['uid'])->get()->first()) {
return send_error('用户不存在', ErrorCode('ARGS'));
}
$pd_user['simple_token'] = 'SP'.$pd_user['id'].'P'.md5(uniqid(rand(), true));
$pd_user->save();
return http_result(['stoken'=>$pd_user['simple_token']]);
}
public function simpleTokenRemove(Request $request)
{
// get user by session
if (!$pd_user = PushDeerUser::where('id', $_SESSION['uid'])->get()->first()) {
return send_error('用户不存在', ErrorCode('ARGS'));
}
$pd_user['simple_token'] = '';
$pd_user->save();
return http_result(['stoken'=>$pd_user['simple_token']]);
}
public function wecode2unionid(Request $request)
{
$validated = $request->validate(
@ -133,6 +186,8 @@ class PushDeerUserController extends Controller
$the_user['level'] = 1;
$pd_user = PushDeerUser::create($the_user);
$pd_user['simple_token'] = 'SP'.$pd_user['id'].'P'.md5(uniqid(rand(), true));
$pd_user->save();
}
// 将数据写到session
@ -141,6 +196,7 @@ class PushDeerUserController extends Controller
$_SESSION['name'] = $pd_user['name'];
$_SESSION['email'] = $pd_user['email'];
$_SESSION['level'] = $pd_user['level'];
$_SESSION['simple_token'] = $pd_user['simple_token'];
session_regenerate_id(true);
$token = session_id();
@ -175,6 +231,8 @@ class PushDeerUserController extends Controller
$the_user['level'] = 1;
$pd_user = PushDeerUser::create($the_user);
$pd_user['simple_token'] = 'SP'.$pd_user['id'].'P'.md5(uniqid(rand(), true));
$pd_user->save();
}
// 将数据写到session
@ -183,6 +241,7 @@ class PushDeerUserController extends Controller
$_SESSION['name'] = $pd_user['name'];
$_SESSION['email'] = $pd_user['email'];
$_SESSION['level'] = $pd_user['level'];
$_SESSION['simple_token'] = $pd_user['simple_token'];
session_regenerate_id(true);
$token = session_id();

View File

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddSimpleTokenToUserTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('push_deer_users', function (Blueprint $table) {
$table->string('simple_token')->nullable();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('push_deer_users', function (Blueprint $table) {
$table->dropColumn('simple_token');
});
}
}

View File

@ -23,6 +23,9 @@ use Illuminate\Support\Facades\Route;
// 假登入,用于测试使用
Route::any('/login/fake', 'App\Http\Controllers\PushDeerUserController@fakeLogin');
// 通过 simple_token 登入
Route::any('/login/simple_token', 'App\Http\Controllers\PushDeerUserController@loginBySimpleToken');
// 通过 apple 返回的 idtoken 登入
Route::post('/login/idtoken', 'App\Http\Controllers\PushDeerUserController@login');
@ -59,6 +62,11 @@ Route::middleware('auto.login')->group(function () {
// 删除一个key
Route::post('/key/remove', 'App\Http\Controllers\PushDeerKeyController@remove');
// simple_token
Route::post('/simple_token/regen', 'App\Http\Controllers\PushDeerUserController@simpleTokenRegen');
Route::post('/simple_token/remove', 'App\Http\Controllers\PushDeerUserController@simpleTokenRemove');
// 消息列表
Route::post('/message/list', 'App\Http\Controllers\PushDeerMessageController@list');
// 删除消息

View File

@ -11,8 +11,8 @@ services:
environment:
- MYSQL_ROOT_PASSWORD=theVeryp@ssw0rd
- MYSQL_DATABASE=pushdeer
ports:
- '3306:3306'
# ports:
# - '3306:3306'
redis:
image: 'bitnami/redis:6.0.16'
healthcheck:
@ -53,4 +53,4 @@ services:
# - MQTT_PASSWORD=y0urp@ss
# - MQTT_BASE_TOPIC=default
volumes:
mariadb_data:
mariadb_data:

View File

@ -1,19 +1,20 @@
version: '2'
services:
app:
image: 'ccr.ccs.tencentyun.com/ftqq/pushdeercore'
ports:
- '9000:9000'
environment:
- DB_HOST=host.docker.internal
- DB_PORT=3306
- DB_USERNAME=root
- DB_DATABASE=pushdeer_local
- DB_PASSWORD=
- DB_TIMEZONE=+08:00
- GO_PUSH_IOS_TOPIC=com.pushdeer.self.ios
- GO_PUSH_IOS_CLIP_TOPIC=com.pushdeer.self.ios.Clip
- APP_DEBUG=false
- WEB_PHP_SOCKET=127.0.0.1:8000
extra_hosts:
- "host.docker.internal:host-gateway"
# 已废弃
# version: '2'
# services:
# app:
# image: 'ccr.ccs.tencentyun.com/ftqq/pushdeercore'
# ports:
# - '9000:9000'
# environment:
# - DB_HOST=host.docker.internal
# - DB_PORT=3306
# - DB_USERNAME=root
# - DB_DATABASE=pushdeer_local
# - DB_PASSWORD=
# - DB_TIMEZONE=+08:00
# - GO_PUSH_IOS_TOPIC=com.pushdeer.self.ios
# - GO_PUSH_IOS_CLIP_TOPIC=com.pushdeer.self.ios.Clip
# - APP_DEBUG=false
# - WEB_PHP_SOCKET=127.0.0.1:8000
# extra_hosts:
# - "host.docker.internal:host-gateway"

View File

@ -49,4 +49,4 @@ SPEC CHECKSUMS:
PODFILE CHECKSUM: 42e3d8abd976589c1043ff9f9e864c275a490160
COCOAPODS: 1.11.2
COCOAPODS: 1.11.3

View File

@ -97,6 +97,9 @@
52EB90B32778DA4E0048E0ED /* Line.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52EB90B22778DA4E0048E0ED /* Line.swift */; };
52EED71E27C9394D0086A804 /* WXDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52EED71D27C9394D0086A804 /* WXDelegate.swift */; };
52EED71F27C93B960086A804 /* WXDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52EED71D27C9394D0086A804 /* WXDelegate.swift */; };
52EF0AFC28CE081A00C99E4F /* CommonUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52EF0AFB28CE081A00C99E4F /* CommonUtils.swift */; };
52EF0AFD28CE081A00C99E4F /* CommonUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52EF0AFB28CE081A00C99E4F /* CommonUtils.swift */; };
52EF0AFE28CE08EC00C99E4F /* CommonUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52EF0AFB28CE081A00C99E4F /* CommonUtils.swift */; };
52F0243F277737470071D861 /* LoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52F0243E277737470071D861 /* LoginView.swift */; };
52F2C223277961D7006F08DC /* SettingsItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52F2C222277961D7006F08DC /* SettingsItemView.swift */; };
52F40D2F277CA05600766C24 /* MessageItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 52F40D2E277CA05600766C24 /* MessageItemView.swift */; };
@ -218,6 +221,7 @@
52EB90AF2778D67F0048E0ED /* KeyItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyItemView.swift; sourceTree = "<group>"; };
52EB90B22778DA4E0048E0ED /* Line.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Line.swift; sourceTree = "<group>"; };
52EED71D27C9394D0086A804 /* WXDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WXDelegate.swift; sourceTree = "<group>"; };
52EF0AFB28CE081A00C99E4F /* CommonUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonUtils.swift; sourceTree = "<group>"; };
52F0243C277733CE0071D861 /* PushDeer.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = PushDeer.entitlements; sourceTree = "<group>"; };
52F0243E277737470071D861 /* LoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginView.swift; sourceTree = "<group>"; };
52F2C222277961D7006F08DC /* SettingsItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsItemView.swift; sourceTree = "<group>"; };
@ -367,6 +371,7 @@
527872C327CE0EE800AD79AD /* Info-SelfHosted.plist */,
52E317DA279305BB000B8BB1 /* Localizable.strings */,
52E317D7279305BB000B8BB1 /* InfoPlist.strings */,
52EF0AFA28CE07A600C99E4F /* Tool */,
52450F362784822C003652D8 /* Service */,
52B8CF5D277DE5FF004CB680 /* Common */,
52450F3D27849228003652D8 /* Model */,
@ -447,6 +452,14 @@
path = Common;
sourceTree = "<group>";
};
52EF0AFA28CE07A600C99E4F /* Tool */ = {
isa = PBXGroup;
children = (
52EF0AFB28CE081A00C99E4F /* CommonUtils.swift */,
);
path = Tool;
sourceTree = "<group>";
};
52F0243D2777370F0071D861 /* View */ = {
isa = PBXGroup;
children = (
@ -776,6 +789,7 @@
5206009E27CF76BC00188431 /* PushDeerApi.swift in Sources */,
520600A627D0AE2300188431 /* Line.swift in Sources */,
5206009D27CF74C100188431 /* HttpRequest.swift in Sources */,
52EF0AFE28CE08EC00C99E4F /* CommonUtils.swift in Sources */,
520600A127CF770600188431 /* Env.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -810,6 +824,7 @@
52EED71E27C9394D0086A804 /* WXDelegate.swift in Sources */,
52EB90AE2778AFD60048E0ED /* BaseNavigationView.swift in Sources */,
524E99E627B3CD0F00292396 /* EndpointView.swift in Sources */,
52EF0AFC28CE081A00C99E4F /* CommonUtils.swift in Sources */,
52EB90AC2778ADF80048E0ED /* CardView.swift in Sources */,
52EB90B02778D67F0048E0ED /* KeyItemView.swift in Sources */,
52AC5C2827B7FE1D00EEB185 /* ViewExtension.swift in Sources */,
@ -853,6 +868,7 @@
52FBA09427874879003308C2 /* ContentView.swift in Sources */,
52B8CF85277E0C12004CB680 /* Line.swift in Sources */,
52AC5C2927B7FE1D00EEB185 /* ViewExtension.swift in Sources */,
52EF0AFD28CE081A00C99E4F /* CommonUtils.swift in Sources */,
52450F402784923D003652D8 /* Result.swift in Sources */,
526A1E712791E00400BA2177 /* PushDeerData.xcdatamodeld in Sources */,
52450F432784943F003652D8 /* HttpRequest.swift in Sources */,

View File

@ -29,6 +29,7 @@ struct UserInfoContent: Codable{
let level: Int
let created_at: String
let updated_at: String
let simple_token: String?
}
struct DeviceItem: Codable, Identifiable{
@ -78,6 +79,12 @@ struct ResultContent: Codable{
let result: Array<String>
}
struct STokenContent: Codable{
let stoken: String?
}
let dateFormatter = DateFormatter()
extension KeyItem {

View File

@ -125,6 +125,35 @@ class AppState: ObservableObject {
}
}
func loginAfter() {
Task {
// UserInfo
self.userInfo = try await HttpRequest.getUserInfo()
var stoken = self.userInfo?.simple_token
if isEmpty(stoken) {
// UserInfo stoken ,
stoken = try await HttpRequest.stokenRegen().stoken
}
if isNotEmpty(stoken) {
// stoken ,
self.saveSTokenToLocal(stoken: stoken)
}
}
}
func saveSTokenToLocal(stoken: String?) -> Void {
let key = "stoken_\(self.api_endpoint)"
getUserDefaults().set(stoken, forKey: key)
}
func getLocalSToken() -> String? {
let key = "stoken_\(self.api_endpoint)"
return getUserDefaults().string(forKey: key)
}
func deleteLocalSToken() -> Void {
let key = "stoken_\(self.api_endpoint)"
getUserDefaults().removeObject(forKey: key)
}
func appleIdLogin(_ result: Result<ASAuthorization, Error>) async throws -> TokenContent {
switch result {
case let .success(authorization):

View File

@ -8,13 +8,63 @@
import Foundation
import Moya
struct TokenAuthorizationPlugin: PluginType {
func prepare(_ request: URLRequest, target: TargetType) -> URLRequest {
if
let url = request.url,
var components = URLComponents(url: url, resolvingAgainstBaseURL: true),
let queryItems = components.queryItems
{
let queryItems_new = queryItems.map { item -> URLQueryItem in
if item.name == "token" {
// token
return URLQueryItem(name: "token", value: AppState.shared.token)
}
return item
}
components.queryItems = queryItems_new
var request_mutable = request
request_mutable.url = components.url
return request_mutable
}
return request
}
}
@MainActor
struct HttpRequest {
static let provider = MoyaProvider<PushDeerApi>(callbackQueue: DispatchQueue.main)
static let provider = MoyaProvider<PushDeerApi>(callbackQueue: DispatchQueue.main, plugins: [TokenAuthorizationPlugin()])
/// , Swift Concurrency (async / await)
static func request<T: Codable>(_ targetType: PushDeerApi, resultType: T.Type) async throws -> T {
do {
return try await _request(targetType, resultType: resultType)
} catch {
if (error as NSError).code == 80403 {
// token
let stoken = AppState.shared.getLocalSToken() // stoken
if isNotEmpty(stoken) {
let token = try? await stokenLogin(stoken: stoken!).token // stoken token
if isNotEmpty(token) {
AppState.shared.token = token! // token
do {
return try await _request(targetType, resultType: resultType) // token
} catch {
throw error //
}
}
AppState.shared.deleteLocalSToken() // stoken , stoken
}
// 退
AppState.shared.token = "" // stoken , token 使
}
throw error // error (stoken, token, )
}
}
static func _request<T: Codable>(_ targetType: PushDeerApi, resultType: T.Type) async throws -> T {
return try await withCheckedThrowingContinuation { continuation in
provider.request(targetType) { result in
switch result {
@ -31,7 +81,6 @@ struct HttpRequest {
if let content = result.content, result.code == 0 {
continuation.resume(returning: content)
} else if result.code == 80403 {
AppState.shared.token = ""
continuation.resume(throwing: NSError(domain: result.error ?? NSLocalizedString("登录过期", comment: "token失效时提示"), code: result.code, userInfo: [NSLocalizedDescriptionKey: result.error ?? NSLocalizedString("登录过期", comment: "token失效时提示")]))
} else {
continuation.resume(throwing: NSError(domain: result.error ?? NSLocalizedString("接口报错", comment: "接口报错时提示"), code: result.code, userInfo: [NSLocalizedDescriptionKey: result.error ?? NSLocalizedString("接口报错", comment: "接口报错时提示")]))
@ -139,4 +188,17 @@ struct HttpRequest {
static func rmAllMessage() async throws -> ActionContent {
return try await request(.rmAllMessage(token: AppState.shared.token), resultType: ActionContent.self)
}
static func stokenLogin(stoken: String) async throws -> TokenContent {
return try await request(.stokenLogin(stoken: stoken), resultType: TokenContent.self)
}
static func stokenRegen() async throws -> STokenContent {
return try await request(.stokenRegen(token: AppState.shared.token), resultType: STokenContent.self)
}
static func stokenRemove() async throws -> STokenContent {
return try await request(.stokenRemove(token: AppState.shared.token), resultType: STokenContent.self)
}
}

View File

@ -42,6 +42,9 @@ enum PushDeerApi {
case rmMessage(token: String, id: Int)
case rmAllMessage(token: String)
case stokenLogin(stoken: String)
case stokenRegen(token: String)
case stokenRemove(token: String)
}
extension PushDeerApi: TargetType {
@ -94,6 +97,13 @@ extension PushDeerApi: TargetType {
return "/message/remove"
case .rmAllMessage:
return "/message/clean"
case .stokenLogin:
return "/login/simple_token"
case .stokenRegen:
return "/simple_token/regen"
case .stokenRemove:
return "/simple_token/remove"
}
}
var method: Moya.Method {
@ -145,6 +155,12 @@ extension PushDeerApi: TargetType {
case let .rmAllMessage(token):
return .requestParameters(parameters: ["token": token],encoding: URLEncoding.queryString)
case let .stokenLogin(stoken):
return .requestParameters(parameters: ["stoken": stoken],encoding: URLEncoding.queryString)
case let .stokenRegen(token):
return .requestParameters(parameters: ["token": token],encoding: URLEncoding.queryString)
case let .stokenRemove(token):
return .requestParameters(parameters: ["token": token],encoding: URLEncoding.queryString)
}
}
var headers: [String: String]? {

View File

@ -30,6 +30,9 @@ class WXDelegate: NSObject, WXApiDelegate {
if state == "login" {
AppState.shared.token = try await HttpRequest.wechatLogin(code: code).token
// AppState token , SwiftUI ContentView
//
AppState.shared.loginAfter()
} else if state == "bind" {
_ = try await HttpRequest.mergeUser(type: "wechat", tokenorcode: code)
// ,

View File

@ -0,0 +1,26 @@
//
// CommonUtils.swift
// PushDeer
//
// Created by HEXT on 2022/9/11.
//
import Foundation
/// ****
/// - Parameter emptiable: , Collection , : String / Array / Dictionary / Set / Data
/// - Returns: nil true
func isEmpty<T: Collection>(_ emptiable: T?) -> Bool {
if emptiable == nil || emptiable!.isEmpty {
return true
} else {
return false
}
}
/// ****
/// - Parameter emptiable: , Collection , : String / Array / Dictionary / Set / Data
/// - Returns: nil false
func isNotEmpty<T: Collection>(_ emptiable: T?) -> Bool {
return !isEmpty(emptiable)
}

View File

@ -41,6 +41,8 @@ struct LoginView: View {
showLoading = true
store.token = try await store.appleIdLogin(result).token
//
//
store.loginAfter()
} catch {
showLoading = false
if (error as NSError).code == 1001 {

View File

@ -21,6 +21,7 @@ struct SettingsView: View {
VStack {
SettingsItemView(title: NSLocalizedString("登录为", comment: "") + " " + userName(), button: NSLocalizedString("退出", comment: "退出登录按钮上的文字")) {
store.token = ""
store.deleteLocalSToken()
HToast.showText(NSLocalizedString("退出", comment: "退出登录按钮上的文字"))
}
.padding(EdgeInsets(top: 18, leading: 20, bottom: 0, trailing: 20))
@ -37,6 +38,7 @@ struct SettingsView: View {
SettingsItemView(title: NSLocalizedString("API endpoint", comment: ""), button: NSLocalizedString("重置", comment: "")) {
store.api_endpoint = ""
store.token = ""
store.deleteLocalSToken()
}
.padding(EdgeInsets(top: 18, leading: 20, bottom: 0, trailing: 20))
}

Binary file not shown.

Binary file not shown.