Skip to content

Commit 9e488a0

Browse files
committed
OAuth2でのログイン処理を追加
2 parents 4735f9b + c966b64 commit 9e488a0

17 files changed

+595
-53
lines changed

GitHubClient/GitHubClient.xcodeproj/project.pbxproj

+8
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
0530756B1FF8CAAF00489708 /* GitHubClient.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 053075611FF8CAAE00489708 /* GitHubClient.framework */; };
1717
053075701FF8CAAF00489708 /* GitHubClientTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0530756F1FF8CAAF00489708 /* GitHubClientTests.swift */; };
1818
053075721FF8CAAF00489708 /* GitHubClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 053075641FF8CAAE00489708 /* GitHubClient.h */; settings = {ATTRIBUTES = (Public, ); }; };
19+
0576AFBA1FFC6BD200235DE5 /* OAuthSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0576AFB91FFC6BD100235DE5 /* OAuthSwift.framework */; };
20+
0576AFBE1FFCBD6D00235DE5 /* GitHubUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0576AFBD1FFCBD6C00235DE5 /* GitHubUser.swift */; };
1921
/* End PBXBuildFile section */
2022

2123
/* Begin PBXContainerItemProxy section */
@@ -41,13 +43,16 @@
4143
0530756A1FF8CAAF00489708 /* GitHubClientTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = GitHubClientTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
4244
0530756F1FF8CAAF00489708 /* GitHubClientTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GitHubClientTests.swift; sourceTree = "<group>"; };
4345
053075711FF8CAAF00489708 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
46+
0576AFB91FFC6BD100235DE5 /* OAuthSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OAuthSwift.framework; path = ../Carthage/Build/iOS/OAuthSwift.framework; sourceTree = "<group>"; };
47+
0576AFBD1FFCBD6C00235DE5 /* GitHubUser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GitHubUser.swift; sourceTree = "<group>"; };
4448
/* End PBXFileReference section */
4549

4650
/* Begin PBXFrameworksBuildPhase section */
4751
0530755D1FF8CAAE00489708 /* Frameworks */ = {
4852
isa = PBXFrameworksBuildPhase;
4953
buildActionMask = 2147483647;
5054
files = (
55+
0576AFBA1FFC6BD200235DE5 /* OAuthSwift.framework in Frameworks */,
5156
052F4D211FF8D129009D8C66 /* Extentions.framework in Frameworks */,
5257
052F4CE71FF8CBDC009D8C66 /* Apollo.framework in Frameworks */,
5358
);
@@ -67,6 +72,7 @@
6772
052F4CE51FF8CBDB009D8C66 /* Frameworks */ = {
6873
isa = PBXGroup;
6974
children = (
75+
0576AFB91FFC6BD100235DE5 /* OAuthSwift.framework */,
7076
052F4D221FF8D129009D8C66 /* Extentions.framework */,
7177
052F4CE61FF8CBDC009D8C66 /* Apollo.framework */,
7278
);
@@ -97,6 +103,7 @@
97103
children = (
98104
053075641FF8CAAE00489708 /* GitHubClient.h */,
99105
052F4CDD1FF8CB6E009D8C66 /* GitHubClient.swift */,
106+
0576AFBD1FFCBD6C00235DE5 /* GitHubUser.swift */,
100107
052F4CDC1FF8CB6E009D8C66 /* GitHubRepository.swift */,
101108
052F4CDA1FF8CB6E009D8C66 /* GitHubGraphQLAPI.graphql */,
102109
052F4CD91FF8CB6D009D8C66 /* GitHubGraphQLAPI.swift */,
@@ -245,6 +252,7 @@
245252
buildActionMask = 2147483647;
246253
files = (
247254
052F4CE31FF8CB6E009D8C66 /* GitHubClient.swift in Sources */,
255+
0576AFBE1FFCBD6D00235DE5 /* GitHubUser.swift in Sources */,
248256
052F4CE21FF8CB6E009D8C66 /* GitHubRepository.swift in Sources */,
249257
052F4CDF1FF8CB6E009D8C66 /* GitHubGraphQLAPI.swift in Sources */,
250258
);

GitHubClient/GitHubClient/GitHubClient.swift

+45-1
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,40 @@ import Foundation
1010
import Apollo
1111
import UIKit
1212
import Extentions
13+
import OAuthSwift
14+
15+
fileprivate let oauthswift = OAuth2Swift(
16+
consumerKey: "4dd6e2ec2e03119aa7bd",
17+
consumerSecret: "6e1847dac03635fa3d0e9de2c28c86f57f4d38b0",
18+
authorizeUrl: "https://github.com/login/oauth/authorize",
19+
accessTokenUrl: "https://github.com/login/oauth/access_token",
20+
responseType: "token"
21+
)
22+
23+
fileprivate let callbackUrl = URL(string: "zizi4n5githubmobile://oauth-callback")!
1324

1425
public class GitHubClient {
1526

27+
static public func login(resultHandler: @escaping ((String?, Error?) -> Swift.Void)) {
28+
29+
let state = generateState(withLength: 20)
30+
let _ = oauthswift.authorize(
31+
withCallbackURL: callbackUrl, scope: "repo", state: state,
32+
success: { credential, response, parameters in
33+
resultHandler(credential.oauthToken, nil)
34+
},
35+
failure: { error in
36+
resultHandler(nil, error)
37+
}
38+
)
39+
}
40+
1641
private let apollo: ApolloClient
42+
public let token: String
1743
public var isLoading = false
18-
44+
1945
public init(token: String) {
46+
self.token = token
2047
let configuration: URLSessionConfiguration = .default
2148
configuration.httpAdditionalHeaders = ["Authorization": "Bearer \(token)"]
2249
configuration.requestCachePolicy = .reloadIgnoringLocalCacheData // To avoid 412
@@ -25,6 +52,23 @@ public class GitHubClient {
2552
apollo = ApolloClient(networkTransport: HTTPNetworkTransport(url: url, configuration: configuration))
2653
}
2754

55+
public func getLoginUser(resultHandler: @escaping ((GitHubUser?, Error?) -> Swift.Void)) {
56+
apollo.fetch(query: LoginUserQuery(), cachePolicy: .fetchIgnoringCacheData) { (result, error) in
57+
58+
if let error = error {
59+
print("Error: \(error)");
60+
return resultHandler(nil, error)
61+
}
62+
63+
guard let name = result?.data?.viewer.name, let avatarUrl = result?.data?.viewer.avatarUrl else {
64+
return resultHandler(nil, error)
65+
}
66+
67+
let user = GitHubUser(name: name, avatarUrl: URL(string: avatarUrl)!)
68+
return resultHandler(user, nil)
69+
}
70+
}
71+
2872
public func getRepositories(first: Int, after: GitHubRepository? = nil, resultHandler: @escaping ((Int, [GitHubRepository], Error?) -> Swift.Void)) {
2973
isLoading = true
3074
let queryString = "language:Swift sort:stars-desc" // 昇順

GitHubClient/GitHubClient/GitHubGraphQLAPI.graphql

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
query LoginUser {
2+
viewer {
3+
name # ログインユーザー名
4+
avatarUrl # ログインユーザーのアバターURL
5+
}
6+
}
7+
18
query SearchRepositories($queryString: String!, $first: Int!, $after: String) {
29
search(query: $queryString, type: REPOSITORY, first: $first after: $after) {
310
repositoryCount # レポジトリ数

GitHubClient/GitHubClient/GitHubGraphQLAPI.swift

+85
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,91 @@
22

33
import Apollo
44

5+
public final class LoginUserQuery: GraphQLQuery {
6+
public static let operationString =
7+
"query LoginUser {\n viewer {\n __typename\n name\n avatarUrl\n }\n}"
8+
9+
public init() {
10+
}
11+
12+
public struct Data: GraphQLSelectionSet {
13+
public static let possibleTypes = ["Query"]
14+
15+
public static let selections: [GraphQLSelection] = [
16+
GraphQLField("viewer", type: .nonNull(.object(Viewer.selections))),
17+
]
18+
19+
public var snapshot: Snapshot
20+
21+
public init(snapshot: Snapshot) {
22+
self.snapshot = snapshot
23+
}
24+
25+
public init(viewer: Viewer) {
26+
self.init(snapshot: ["__typename": "Query", "viewer": viewer.snapshot])
27+
}
28+
29+
/// The currently authenticated user.
30+
public var viewer: Viewer {
31+
get {
32+
return Viewer(snapshot: snapshot["viewer"]! as! Snapshot)
33+
}
34+
set {
35+
snapshot.updateValue(newValue.snapshot, forKey: "viewer")
36+
}
37+
}
38+
39+
public struct Viewer: GraphQLSelectionSet {
40+
public static let possibleTypes = ["User"]
41+
42+
public static let selections: [GraphQLSelection] = [
43+
GraphQLField("__typename", type: .nonNull(.scalar(String.self))),
44+
GraphQLField("name", type: .scalar(String.self)),
45+
GraphQLField("avatarUrl", type: .nonNull(.scalar(String.self))),
46+
]
47+
48+
public var snapshot: Snapshot
49+
50+
public init(snapshot: Snapshot) {
51+
self.snapshot = snapshot
52+
}
53+
54+
public init(name: String? = nil, avatarUrl: String) {
55+
self.init(snapshot: ["__typename": "User", "name": name, "avatarUrl": avatarUrl])
56+
}
57+
58+
public var __typename: String {
59+
get {
60+
return snapshot["__typename"]! as! String
61+
}
62+
set {
63+
snapshot.updateValue(newValue, forKey: "__typename")
64+
}
65+
}
66+
67+
/// The user's public profile name.
68+
public var name: String? {
69+
get {
70+
return snapshot["name"] as? String
71+
}
72+
set {
73+
snapshot.updateValue(newValue, forKey: "name")
74+
}
75+
}
76+
77+
/// A URL pointing to the user's public avatar.
78+
public var avatarUrl: String {
79+
get {
80+
return snapshot["avatarUrl"]! as! String
81+
}
82+
set {
83+
snapshot.updateValue(newValue, forKey: "avatarUrl")
84+
}
85+
}
86+
}
87+
}
88+
}
89+
590
public final class SearchRepositoriesQuery: GraphQLQuery {
691
public static let operationString =
792
"query SearchRepositories($queryString: String!, $first: Int!, $after: String) {\n search(query: $queryString, type: REPOSITORY, first: $first, after: $after) {\n __typename\n repositoryCount\n edges {\n __typename\n node {\n __typename\n ... on Repository {\n name\n nameWithOwner\n owner {\n __typename\n login\n avatarUrl\n }\n shortDescriptionHTML\n repositoryTopics(first: 100) {\n __typename\n edges {\n __typename\n node {\n __typename\n topic {\n __typename\n name\n }\n }\n }\n }\n primaryLanguage {\n __typename\n name\n color\n }\n stargazers {\n __typename\n totalCount\n }\n url\n updatedAt\n }\n }\n cursor\n }\n pageInfo {\n __typename\n endCursor\n hasNextPage\n hasPreviousPage\n startCursor\n }\n }\n}"
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//
2+
// GitHubRepository.swift
3+
// GitHubMobile
4+
//
5+
// Created by zizi4n5 on 2017/12/29.
6+
// Copyright © 2017年 zizi4n5. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import UIKit
11+
import Apollo
12+
13+
14+
public class GitHubUser {
15+
16+
public var name: String!
17+
public var avatarUrl: URL!
18+
19+
public init(name: String, avatarUrl: URL) {
20+
self.name = name
21+
self.avatarUrl = avatarUrl
22+
}
23+
}

GitHubMobile.xcodeproj/project.pbxproj

+6-2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
055776681FF9F0C5006D9402 /* HidingNavigationBar.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 055776651FF9F0BD006D9402 /* HidingNavigationBar.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
3333
056205E31FF62B510044CB85 /* RepositoryCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 056205E11FF62B510044CB85 /* RepositoryCell.swift */; };
3434
056205E61FF6329E0044CB85 /* RepositoryTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 056205E51FF6329E0044CB85 /* RepositoryTableViewController.swift */; };
35+
0576AFBC1FFC882F00235DE5 /* LoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0576AFBB1FFC882F00235DE5 /* LoginViewController.swift */; };
3536
05D4C4241FFA0A3000E6A443 /* OAuthSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05D4C4221FFA0A2C00E6A443 /* OAuthSwift.framework */; };
3637
05D4C4251FFA0A3000E6A443 /* OAuthSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 05D4C4221FFA0A2C00E6A443 /* OAuthSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
3738
05D4C42A1FFA14F800E6A443 /* KeychainAccess.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 05D4C4281FFA14F300E6A443 /* KeychainAccess.framework */; };
@@ -103,6 +104,7 @@
103104
056205DA1FF60ECF0044CB85 /* Apollo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Apollo.framework; path = Carthage/Build/iOS/Apollo.framework; sourceTree = "<group>"; };
104105
056205E11FF62B510044CB85 /* RepositoryCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepositoryCell.swift; sourceTree = "<group>"; };
105106
056205E51FF6329E0044CB85 /* RepositoryTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RepositoryTableViewController.swift; sourceTree = "<group>"; };
107+
0576AFBB1FFC882F00235DE5 /* LoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewController.swift; sourceTree = "<group>"; };
106108
05D4C4221FFA0A2C00E6A443 /* OAuthSwift.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OAuthSwift.framework; path = Carthage/Build/iOS/OAuthSwift.framework; sourceTree = "<group>"; };
107109
05D4C4281FFA14F300E6A443 /* KeychainAccess.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = KeychainAccess.framework; path = Carthage/Build/iOS/KeychainAccess.framework; sourceTree = "<group>"; };
108110
1AE25C49D2BEE304D3551EC2 /* Pods-GitHubMobile.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GitHubMobile.release.xcconfig"; path = "Pods/Target Support Files/Pods-GitHubMobile/Pods-GitHubMobile.release.xcconfig"; sourceTree = "<group>"; };
@@ -174,6 +176,7 @@
174176
0541D39E1FF3AB9A006DED14 /* Main.storyboard */,
175177
0541D39A1FF3AB9A006DED14 /* AppDelegate.swift */,
176178
0557765E1FF9B080006D9402 /* UIView+Extension.swift */,
179+
0576AFBB1FFC882F00235DE5 /* LoginViewController.swift */,
177180
056205E51FF6329E0044CB85 /* RepositoryTableViewController.swift */,
178181
056205E11FF62B510044CB85 /* RepositoryCell.swift */,
179182
0530754C1FF6817200489708 /* RepositoryDetailViewController.swift */,
@@ -366,7 +369,7 @@
366369
/* Begin PBXShellScriptBuildPhase section */
367370
053075541FF8686F00489708 /* Run Script (License Plist) */ = {
368371
isa = PBXShellScriptBuildPhase;
369-
buildActionMask = 2147483647;
372+
buildActionMask = 12;
370373
files = (
371374
);
372375
inputPaths = (
@@ -376,7 +379,7 @@
376379
);
377380
runOnlyForDeploymentPostprocessing = 0;
378381
shellPath = /bin/sh;
379-
shellScript = "if [ $CONFIGURATION = \"Debug\" ] && [ -e /usr/local/bin/license-plist ]; then\n/usr/local/bin/license-plist --output-path $PRODUCT_NAME/Settings.bundle --github-token 48260fb231e733ce5dde9fc26aa6b1f6ec3714a7 --suppress-opening-directory\nfi";
382+
shellScript = "if [ $CONFIGURATION = \"Debug\" ] && [ -e /usr/local/bin/license-plist ] && [ $GITHUB_TOKEN_LICENSE_PLIST ]; then\n/usr/local/bin/license-plist --output-path $PRODUCT_NAME/Settings.bundle --github-token $GITHUB_TOKEN_LICENSE_PLIST --suppress-opening-directory --add-version-numbers\nfi";
380383
};
381384
D17C3A15C7B857EF8B070296 /* [CP] Copy Pods Resources */ = {
382385
isa = PBXShellScriptBuildPhase;
@@ -436,6 +439,7 @@
436439
isa = PBXSourcesBuildPhase;
437440
buildActionMask = 2147483647;
438441
files = (
442+
0576AFBC1FFC882F00235DE5 /* LoginViewController.swift in Sources */,
439443
056205E61FF6329E0044CB85 /* RepositoryTableViewController.swift in Sources */,
440444
0530754D1FF6817200489708 /* RepositoryDetailViewController.swift in Sources */,
441445
056205E31FF62B510044CB85 /* RepositoryCell.swift in Sources */,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"info" : {
3+
"version" : 1,
4+
"author" : "xcode"
5+
}
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"images" : [
3+
{
4+
"idiom" : "universal",
5+
"scale" : "1x"
6+
},
7+
{
8+
"idiom" : "universal",
9+
"filename" : "LaunchScreen.png",
10+
"scale" : "2x"
11+
},
12+
{
13+
"idiom" : "universal",
14+
"scale" : "3x"
15+
}
16+
],
17+
"info" : {
18+
"version" : 1,
19+
"author" : "xcode"
20+
}
21+
}
Loading

0 commit comments

Comments
 (0)