Skip to content

Commit c5a5664

Browse files
committed
Close #25: Login
1 parent 3b93de2 commit c5a5664

File tree

37 files changed

+669
-375
lines changed

37 files changed

+669
-375
lines changed

FetchTestResponses.sh

Lines changed: 0 additions & 143 deletions
This file was deleted.

Package.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ let package = Package(
1717
],
1818
products: [
1919
.library(name: "Rainmaker", targets: ["Rainmaker"]),
20-
.executable(name: "RainmakerCLI", targets: ["RainmakerCLI"]),
21-
.library(name: "RainmakerMocks", targets: ["RainmakerMocks"]),
20+
.executable(name: "rainmaker-cli", targets: ["RainmakerCLI"]),
2221
],
2322
dependencies: [
2423
.package(url: "https://github.com/apple/swift-argument-parser", from: "1.6.2"),
@@ -30,7 +29,6 @@ let package = Package(
3029
.product(name: "ArgumentParser", package: "swift-argument-parser"),
3130
"Rainmaker",
3231
]),
33-
.target(name: "RainmakerMocks", dependencies: ["Rainmaker"]),
3432
.testTarget(name: "RainmakerTests", dependencies: ["Rainmaker"], resources: [.copy("Responses")]),
3533
]
3634
)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Command Line Interface
2+
3+
This package also provides a convenient executable to leverage the features of the library in a terminal environment.
4+
5+
## Overview
6+
7+
You can get an overview by running the command line interface itself or any subcommand with the `--help` option in the package root directory like this:
8+
9+
```plaintext
10+
$ swift run rainmaker-cli --help
11+
USAGE: rainmaker <subcommand>
12+
13+
OPTIONS:
14+
-h, --help Show help information.
15+
16+
SUBCOMMANDS:
17+
list List the content of a directory on the server by the given path.
18+
login Fetch the login flow information from a server.
19+
poll Poll the status of a previously initiated login flow.
20+
21+
See 'rainmaker help <subcommand>' for detailed help.
22+
```

Sources/Rainmaker/Documentation.docc/Documentation.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,17 @@ A simple Swift library to interact with Nextcloud programmatically.
66

77
### Services
88

9-
- ``Requesting``
109
- ``Server``
11-
- ``Serving``
1210

1311
### Data Models
1412

1513
- ``Item``
1614
- ``Lock``
15+
- ``LoginFlow``
16+
- ``LoginResult``
1717
- ``Permission``
1818
- ``User``
19+
20+
### Command Line Interface
21+
22+
- <doc:CommandLineInterface>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// SPDX-FileCopyrightText: 2025 Iva Horn
2+
// SPDX-License-Identifier: MIT
3+
4+
import Foundation
5+
6+
///
7+
/// All the necessary information to begin and monitor a client login flow.
8+
///
9+
public struct LoginFlow: Model {
10+
///
11+
/// The endpoint to poll for the status.
12+
///
13+
public let endpoint: URL
14+
15+
///
16+
/// The initial web page to present to the user for logging in.
17+
///
18+
public let entry: URL
19+
20+
///
21+
/// The token the specific login flow is identified by.
22+
///
23+
public let token: String
24+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// SPDX-FileCopyrightText: 2025 Iva Horn
2+
// SPDX-License-Identifier: MIT
3+
4+
import Foundation
5+
6+
///
7+
/// The result of a successfully completed login flow.
8+
///
9+
public struct LoginResult: Model {
10+
///
11+
/// The user name to log in with.
12+
///
13+
public let name: String
14+
15+
///
16+
/// The (app) password provided by the server.
17+
///
18+
public let password: String
19+
20+
///
21+
/// The final server address itself.
22+
///
23+
public let server: URL
24+
}

Sources/Rainmaker/Models/Method.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
/// HTTP request methods.
66
///
77
enum Method: String, RawRepresentable {
8+
///
9+
/// Sending data to a resource.
10+
///
11+
case post = "POST"
12+
813
///
914
/// Fetch properties of remote items.
1015
///

Sources/Rainmaker/Models/Permission.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public enum Permission: Character, Model {
5959

6060
for character in compound {
6161
guard let permission = Self(rawValue: character) else {
62-
throw RainmakerError.responseDecodingFailed("Unknown permission character: \(character)")
62+
throw RainmakerError.responseDecodingFailed(reason: "Unknown permission character: \(character)")
6363
}
6464

6565
permissions.insert(permission)

Sources/Rainmaker/Models/RainmakerError.swift

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,28 @@ import Foundation
66
///
77
/// Semantic errors specific to this library.
88
///
9-
enum RainmakerError: Error, CustomStringConvertible {
9+
public enum RainmakerError: Error, Equatable, CustomStringConvertible {
10+
///
11+
/// The intended action requires credentials like user name and password but they were not given.
12+
///
13+
case credentialsRequired
14+
1015
///
1116
/// The response most likely was not in the expected format or structure.
1217
///
13-
case responseDecodingFailed(_ reason: String)
18+
/// - Parameters:
19+
/// - reason: A human readable explanation why it failed.
20+
///
21+
case responseDecodingFailed(reason: String)
1422

15-
var description: String {
23+
///
24+
/// For conformance to `CustomStringConvertible` to render an error as a human readable error description.
25+
///
26+
public var description: String {
1627
switch self {
17-
case let .responseDecodingFailed(reason):
28+
case .credentialsRequired:
29+
"Credentials required"
30+
case let .responseDecodingFailed(reason: reason):
1831
reason
1932
}
2033
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// SPDX-FileCopyrightText: 2025 Iva Horn
2+
// SPDX-License-Identifier: MIT
3+
4+
import Foundation
5+
6+
///
7+
/// This is the JSON response as returned by the server.
8+
///
9+
/// This is a data transfer object and is converted to a ``LoginFlow`` for external callers.
10+
///
11+
struct LoginFlowResponse: Decodable {
12+
struct Poll: Decodable {
13+
let endpoint: URL
14+
let token: String
15+
}
16+
17+
let login: URL
18+
let poll: Poll
19+
}

0 commit comments

Comments
 (0)