From fc64540723ecbee3b8c9eb83aa306223caead0e6 Mon Sep 17 00:00:00 2001 From: Aakiyaru Date: Tue, 27 May 2025 14:10:15 +0700 Subject: [PATCH] auth --- NetworkApi/.gitignore | 8 +++ NetworkApi/Package.swift | 24 ++++++++ .../Sources/NetworkApi/NetworkApi.swift | 2 + .../NetworkApiTests/NetworkApiTests.swift | 12 ++++ Package.resolved | 15 +++++ Package.swift | 27 ++++++++ Sources/NetworkApi/Common/Headers.swift | 28 +++++++++ Sources/NetworkApi/Common/URLS.swift | 18 ++++++ .../Interfaces/BaseNetworkService.swift | 29 +++++++++ .../BaseNetworkServiceProtocol.swift | 10 +++ .../Models/ServerResponseAuth.swift | 44 +++++++++++++ .../Models/ServerResponseIdToken.swift | 17 ++++++ .../Models/ServerResponseRegister.swift | 34 +++++++++++ .../NetworkLayer/Auth/NetworkAuth.swift | 61 +++++++++++++++++++ .../Auth/NetworkAuthProtocol.swift | 16 +++++ Tests/NetworkApiTests/NetworkApiTests.swift | 12 ++++ 16 files changed, 357 insertions(+) create mode 100644 NetworkApi/.gitignore create mode 100644 NetworkApi/Package.swift create mode 100644 NetworkApi/Sources/NetworkApi/NetworkApi.swift create mode 100644 NetworkApi/Tests/NetworkApiTests/NetworkApiTests.swift create mode 100644 Package.resolved create mode 100644 Package.swift create mode 100644 Sources/NetworkApi/Common/Headers.swift create mode 100644 Sources/NetworkApi/Common/URLS.swift create mode 100644 Sources/NetworkApi/Interfaces/BaseNetworkService.swift create mode 100644 Sources/NetworkApi/Interfaces/BaseNetworkServiceProtocol.swift create mode 100644 Sources/NetworkApi/Models/ServerResponseAuth.swift create mode 100644 Sources/NetworkApi/Models/ServerResponseIdToken.swift create mode 100644 Sources/NetworkApi/Models/ServerResponseRegister.swift create mode 100644 Sources/NetworkApi/NetworkLayer/Auth/NetworkAuth.swift create mode 100644 Sources/NetworkApi/NetworkLayer/Auth/NetworkAuthProtocol.swift create mode 100644 Tests/NetworkApiTests/NetworkApiTests.swift diff --git a/NetworkApi/.gitignore b/NetworkApi/.gitignore new file mode 100644 index 0000000..0023a53 --- /dev/null +++ b/NetworkApi/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/NetworkApi/Package.swift b/NetworkApi/Package.swift new file mode 100644 index 0000000..78c7d54 --- /dev/null +++ b/NetworkApi/Package.swift @@ -0,0 +1,24 @@ +// swift-tools-version: 6.0 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "NetworkApi", + products: [ + // Products define the executables and libraries a package produces, making them visible to other packages. + .library( + name: "NetworkApi", + targets: ["NetworkApi"]), + ], + targets: [ + // Targets are the basic building blocks of a package, defining a module or a test suite. + // Targets can depend on other targets in this package and products from dependencies. + .target( + name: "NetworkApi"), + .testTarget( + name: "NetworkApiTests", + dependencies: ["NetworkApi"] + ), + ] +) diff --git a/NetworkApi/Sources/NetworkApi/NetworkApi.swift b/NetworkApi/Sources/NetworkApi/NetworkApi.swift new file mode 100644 index 0000000..08b22b8 --- /dev/null +++ b/NetworkApi/Sources/NetworkApi/NetworkApi.swift @@ -0,0 +1,2 @@ +// The Swift Programming Language +// https://docs.swift.org/swift-book diff --git a/NetworkApi/Tests/NetworkApiTests/NetworkApiTests.swift b/NetworkApi/Tests/NetworkApiTests/NetworkApiTests.swift new file mode 100644 index 0000000..4c36569 --- /dev/null +++ b/NetworkApi/Tests/NetworkApiTests/NetworkApiTests.swift @@ -0,0 +1,12 @@ +import XCTest +@testable import NetworkApi + +final class NetworkApiTests: XCTestCase { + func testExample() throws { + // XCTest Documentation + // https://developer.apple.com/documentation/xctest + + // Defining Test Cases and Test Methods + // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods + } +} diff --git a/Package.resolved b/Package.resolved new file mode 100644 index 0000000..b189e91 --- /dev/null +++ b/Package.resolved @@ -0,0 +1,15 @@ +{ + "originHash" : "068ba4d664f0065a1b9c7d7d2d9ac8794687caa353c7943f0ca8dd1e432db8e1", + "pins" : [ + { + "identity" : "alamofire", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Alamofire/Alamofire", + "state" : { + "revision" : "513364f870f6bfc468f9d2ff0a95caccc10044c5", + "version" : "5.10.2" + } + } + ], + "version" : 3 +} diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..014e1e3 --- /dev/null +++ b/Package.swift @@ -0,0 +1,27 @@ +// swift-tools-version: 6.0 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "NetworkApi", + platforms: [.iOS(.v17)], + products: [ + // Products define the executables and libraries a package produces, making them visible to other packages. + .library( + name: "NetworkApi", + targets: ["NetworkApi"]), + ], + dependencies: [.package(url: "https://github.com/Alamofire/Alamofire", from: "5.8.0")], + targets: [ + // Targets are the basic building blocks of a package, defining a module or a test suite. + // Targets can depend on other targets in this package and products from dependencies. + .target( + name: "NetworkApi", + dependencies: ["Alamofire"]), + .testTarget( + name: "NetworkApiTests", + dependencies: ["NetworkApi"] + ), + ] +) diff --git a/Sources/NetworkApi/Common/Headers.swift b/Sources/NetworkApi/Common/Headers.swift new file mode 100644 index 0000000..bc7fea7 --- /dev/null +++ b/Sources/NetworkApi/Common/Headers.swift @@ -0,0 +1,28 @@ +// +// File.swift +// NetworkApi +// +// Created by User on 27.05.2025. +// + +import Foundation +import Alamofire + +public final class Headers { + + static func headers() -> HTTPHeaders { + return [ + .contentType("application/json"), + .accept("application/json") + ] + } + + static func headerWithToken(token: String) -> HTTPHeaders { + return [ + .contentType("application/json"), + .accept("application/json"), + .authorization(bearerToken: token) + ] + } + +} diff --git a/Sources/NetworkApi/Common/URLS.swift b/Sources/NetworkApi/Common/URLS.swift new file mode 100644 index 0000000..e1dbf8c --- /dev/null +++ b/Sources/NetworkApi/Common/URLS.swift @@ -0,0 +1,18 @@ +// +// File.swift +// NetworkApi +// +// Created by User on 27.05.2025. +// + +import Foundation + +public struct URLS { + static let baseURL = "https://api.matule.ru/api/collections" + static let register = "users/records" + static let getUserInfo = "users/records/" + static let updateUserInfo = "users/records/" + static let login = "users/auth-with-password" + static let getIdToken = "_authOrigins/records" + static let deleteUser = "_authOrigins/records/" +} diff --git a/Sources/NetworkApi/Interfaces/BaseNetworkService.swift b/Sources/NetworkApi/Interfaces/BaseNetworkService.swift new file mode 100644 index 0000000..3bbcfee --- /dev/null +++ b/Sources/NetworkApi/Interfaces/BaseNetworkService.swift @@ -0,0 +1,29 @@ +// The Swift Programming Language +// https://docs.swift.org/swift-book + +import Alamofire +import Foundation + +public final class BaseNetworkService: BaseNetworkServiceProtocol { + + public var baseURL: String? + + public func execute(path: String, method: HTTPMethod, parameters: Parameters, headers: HTTPHeaders) async throws -> Data { + guard let baseURL = baseURL else { + fatalError("Error baseURL") + } + + let stringURL = baseURL + "/" + path + + let data = try await AF.request(stringURL, method: method, parameters: parameters, encoding: JSONEncoding.default, headers: headers).serializingData().value + + return data + + } + + public func configure(baseURL: String) { + self.baseURL = baseURL + } + + +} diff --git a/Sources/NetworkApi/Interfaces/BaseNetworkServiceProtocol.swift b/Sources/NetworkApi/Interfaces/BaseNetworkServiceProtocol.swift new file mode 100644 index 0000000..8db4ff0 --- /dev/null +++ b/Sources/NetworkApi/Interfaces/BaseNetworkServiceProtocol.swift @@ -0,0 +1,10 @@ +// The Swift Programming Language +// https://docs.swift.org/swift-book + +import Alamofire +import Foundation + +public protocol BaseNetworkServiceProtocol { + func execute(path: String, method: HTTPMethod, headers: HTTPHeaders, parameters: Parameters) async throws -> Data + func configure(baseURL: String) +} diff --git a/Sources/NetworkApi/Models/ServerResponseAuth.swift b/Sources/NetworkApi/Models/ServerResponseAuth.swift new file mode 100644 index 0000000..db65087 --- /dev/null +++ b/Sources/NetworkApi/Models/ServerResponseAuth.swift @@ -0,0 +1,44 @@ +// +// File.swift +// NetworkApi +// +// Created by User on 27.05.2025. +// + +import Foundation + +//{ +// "record": { +// "collectionId": "_pb_users_auth_", +// "collectionName": "users", +// "created": "2025-05-27 06:07:03.550Z", +// "dateBirthday": "", +// "email": "exwefwefample@test.ru", +// "emailVisibility": false, +// "firstname": "", +// "gender": "", +// "id": "0et69a89t2nyvvc", +// "lastname": "", +// "secondname": "", +// "updated": "2025-05-27 06:07:03.550Z", +// "verified": false +// }, +// "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjb2xsZWN0aW9uSWQiOiJfcGJfdXNlcnNfYXV0aF8iLCJleHAiOjE3NDg5MzEwOTQsImlkIjoiMGV0NjlhODl0Mm55dnZjIiwicmVmcmVzaGFibGUiOnRydWUsInR5cGUiOiJhdXRoIn0.UlCEyQVSAQ51Euo1UGGIol6s9oqIPUG4kOOFZ9gWgwE" +//} + +public struct ServerResponseAuth: Decodable { + let record: RecordAuth + let token: String + + struct RecordAuth: Decodable { + let collectionId: String + let collectionName: String + let dateBirthday: String + let email: String + let firstname: String + let gender: String + let id: String + let lastname: String + let secondname: String + } +} diff --git a/Sources/NetworkApi/Models/ServerResponseIdToken.swift b/Sources/NetworkApi/Models/ServerResponseIdToken.swift new file mode 100644 index 0000000..a0a9f30 --- /dev/null +++ b/Sources/NetworkApi/Models/ServerResponseIdToken.swift @@ -0,0 +1,17 @@ +// +// File.swift +// NetworkApi +// +// Created by User on 27.05.2025. +// + +import Foundation + +struct ServerResponseIdToken: Decodable { + let items: IdToken + + struct IdToken: Decodable { + let id: String + } +} + diff --git a/Sources/NetworkApi/Models/ServerResponseRegister.swift b/Sources/NetworkApi/Models/ServerResponseRegister.swift new file mode 100644 index 0000000..0f71a3a --- /dev/null +++ b/Sources/NetworkApi/Models/ServerResponseRegister.swift @@ -0,0 +1,34 @@ +// +// File.swift +// NetworkApi +// +// Created by User on 27.05.2025. +// + +import Foundation + +//{ +// "collectionId": "_pb_users_auth_", +// "collectionName": "users", +// "created": "2025-05-27 06:07:03.550Z", +// "dateBirthday": "", +// "emailVisibility": false, +// "firstname": "", +// "gender": "", +// "id": "0et69a89t2nyvvc", +// "lastname": "", +// "secondname": "", +// "updated": "2025-05-27 06:07:03.550Z", +// "verified": false +//} + +public struct ServerResponseRegister: Decodable { + let collectionId: String + let collectionName: String + let dateBirthday: String + let firstname: String + let gender: String + let id: String + let lastname: String + let secondname: String +} diff --git a/Sources/NetworkApi/NetworkLayer/Auth/NetworkAuth.swift b/Sources/NetworkApi/NetworkLayer/Auth/NetworkAuth.swift new file mode 100644 index 0000000..e3d022e --- /dev/null +++ b/Sources/NetworkApi/NetworkLayer/Auth/NetworkAuth.swift @@ -0,0 +1,61 @@ +// +// File.swift +// NetworkApi +// +// Created by User on 27.05.2025. +// + +import Foundation + +public final class NetworkUser: NetworkUserProtocol { + + let baseUrl: BaseNetworkServiceProtocol + + init(baseUrl: BaseNetworkServiceProtocol) { + self.baseUrl = baseUrl + } + + public func login(identity: String, password: String) async throws -> ServerResponseAuth { + let data = try await baseUrl.execute(path: URLS.login, method: .post, headers: Headers.headers(), parameters: [ + "identity": identity, + "password": password + ]) + return try JSONDecoder().decode(ServerResponseAuth.self, from: data) + } + + public func register(email: String, password: String, passwordConfirm: String, firstname: String, lastname: String, secondname: String, datebirthday: String, gender: String) async throws -> ServerResponseRegister { + let data = try await baseUrl.execute(path: URLS.register, method: .post, headers: Headers.headers(), parameters: [ + "email": email, + "password": password, + "passwordConfirm": passwordConfirm + ]) + let result = try JSONDecoder().decode(ServerResponseRegister.self, from: data) + let addUserResult = try await addUser(idUser: result.id, email: email, firstname: firstname, lastname: lastname, secondname: secondname, datebirthday: datebirthday, gender: gender) + return addUserResult + } + + public func addUser(idUser: String, email: String, firstname: String, lastname: String, secondname: String, datebirthday: String, gender: String) async throws -> ServerResponseRegister { + let data = try await baseUrl.execute(path: URLS.login, method: .put, headers: Headers.headerWithToken(token: ""), parameters: [ + "email" : email, + "emailVisibility" : true, + "firstname" : firstname, + "lastname" : lastname, + "secondname" : secondname, + "datebirthday" : datebirthday, + "gender" : gender + ]) + return try JSONDecoder().decode(ServerResponseRegister.self, from: data) + } + + public func getIdToken(token: String) async throws -> String { + let data = try await baseUrl.execute(path: URLS.getIdToken, method: .get, headers: Headers.headerWithToken(token: token), parameters: ["":""]) + let tokenID = try JSONDecoder().decode(ServerResponseIdToken.self, from: data) + return tokenID.items.id + } + + public func deleteUser(idToken: String, token: String) async throws { + let data = try await baseUrl.execute(path: URLS.deleteUser, method: .delete, headers: Headers.headerWithToken(token: token), parameters: ["id_token":idToken]) + } + + +} diff --git a/Sources/NetworkApi/NetworkLayer/Auth/NetworkAuthProtocol.swift b/Sources/NetworkApi/NetworkLayer/Auth/NetworkAuthProtocol.swift new file mode 100644 index 0000000..5e70ad2 --- /dev/null +++ b/Sources/NetworkApi/NetworkLayer/Auth/NetworkAuthProtocol.swift @@ -0,0 +1,16 @@ +// +// File.swift +// NetworkApi +// +// Created by User on 27.05.2025. +// + +import Foundation + +public protocol NetworkUserProtocol { + func login(identity: String, password: String) async throws -> ServerResponseAuth + func register(email: String, password: String, passwordConfirm: String, firstname: String, lastname: String, secondname: String, datebirthday: String, gender: String) async throws -> ServerResponseRegister + func addUser(idUser: String, email: String, firstname: String, lastname: String, secondname: String, datebirthday: String, gender: String) async throws -> ServerResponseRegister + func getIdToken(token: String) async throws -> String + func deleteUser(idToken: String, token: String) async throws +} diff --git a/Tests/NetworkApiTests/NetworkApiTests.swift b/Tests/NetworkApiTests/NetworkApiTests.swift new file mode 100644 index 0000000..4c36569 --- /dev/null +++ b/Tests/NetworkApiTests/NetworkApiTests.swift @@ -0,0 +1,12 @@ +import XCTest +@testable import NetworkApi + +final class NetworkApiTests: XCTestCase { + func testExample() throws { + // XCTest Documentation + // https://developer.apple.com/documentation/xctest + + // Defining Test Cases and Test Methods + // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods + } +}