Skip to content

Commit aa168f8

Browse files
committed
init
1 parent 8b1fecd commit aa168f8

14 files changed

+657
-1
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Xcode
2+
Packages
3+
.build

LICENCE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2016 Slimane
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

Makefile

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
CLibUv=CLibUv-*
2+
COpenSSL=COpenSSL-*
3+
BUILDOPTS=-Xlinker -L/usr/lib -Xcc -IPackages/$(CLibUv) -Xcc -IPackages/$(COpenSSL)
4+
5+
SWIFTC=swiftc
6+
SWIFT=swift
7+
ifdef SWIFTPATH
8+
SWIFTC=$(SWIFTPATH)/bin/swiftc
9+
SWIFT=$(SWIFTPATH)/bin/swift
10+
endif
11+
OS := $(shell uname)
12+
ifeq ($(OS),Darwin)
13+
SWIFTC=xcrun -sdk macosx swiftc
14+
BUILDOPTS=-Xlinker -L/usr/local/lib -Xcc -I/usr/local/include
15+
endif
16+
17+
all: release
18+
19+
debug:
20+
$(SWIFT) build -v $(BUILDOPTS)
21+
22+
release:
23+
$(SWIFT) build -v $(BUILDOPTS) --configuration=release
24+
25+
test:
26+
$(SWIFT) test

Package.swift

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import PackageDescription
2+
3+
let package = Package(
4+
name: "SessionMiddleware",
5+
dependencies: [
6+
.Package(url: "https://github.com/slimane-swift/Middleware.git", majorVersion: 0, minor: 1),
7+
.Package(url: "https://github.com/noppoMan/Crypto.git", majorVersion: 0, minor: 1),
8+
.Package(url: "https://github.com/noppoMan/Suv.git", majorVersion: 0, minor: 2)
9+
]
10+
)

README.md

+146-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,146 @@
1-
# SessionMIddleware
1+
# SessionMiddleware
2+
3+
Session Middleware for Slimane
4+
5+
6+
## Usage
7+
```swift
8+
import Slimane
9+
import SessionMiddleware
10+
11+
let app = Slimane()
12+
13+
// SessionConfig
14+
let sesConf = SessionConfig(
15+
secret: "my-secret-value",
16+
expires: 180,
17+
HTTPOnly: true
18+
)
19+
20+
// Enable to use session in Slimane
21+
app.use(SessionMiddleware(conf: sesConf))
22+
```
23+
24+
## Apis
25+
26+
### SessionMiddleware
27+
28+
Middleware for session handling in Slimane
29+
30+
```swift
31+
SessionMiddleware(conf: SessionConfig)
32+
```
33+
34+
### SessionConfig
35+
36+
Session Configuration Struct.
37+
38+
#### Members
39+
* store: SessionStoreType
40+
- Default store is the SessionMemoryStore
41+
* keyName: String
42+
* secret: String
43+
- Your application secret value
44+
* expires: Int?
45+
- Sec for cookie/stored data ttl
46+
* HTTPOnly: Bool
47+
* secure: Bool
48+
* maxAge: Int?
49+
* domain: String?
50+
* path: String?
51+
52+
53+
### SessionStoreType
54+
55+
```swift
56+
public protocol SessionStoreType {
57+
func destroy(sessionId: String)
58+
func load(sessionId: String, completion: (SessionResult<[String: AnyObject?]>) -> Void)
59+
func store(sessionId: String, values: [String: AnyObject?], expires: Int?, completion: () -> Void)
60+
}
61+
```
62+
63+
### SessionMemoryStore
64+
65+
SessionMemoryStore is default store for SessionMiddleware.
66+
And this is not recommended to use under production environment.
67+
68+
### SerializerType
69+
70+
Protocol for Serializer
71+
72+
```swift
73+
public protocol SerializerType {
74+
func serialize(src: [String: AnyObject]) throws -> String
75+
func deserialize(src: String) throws -> [String: AnyObject]
76+
}
77+
```
78+
79+
### JsonSerializer
80+
81+
Serialize/deserialize the value with JSON format
82+
83+
```swift
84+
let serializer = JsonSerializer()
85+
86+
let serialized = serializer.serializer(["foo": "bar"])
87+
88+
print(serializer.deserialize(serialized))
89+
```
90+
91+
## Create your own SessionStore
92+
93+
Easy to make an own SessionStore with confirming SessionStoreType. Here is an easy FileSessionStore Example.
94+
95+
```swift
96+
import SessionMiddleware
97+
import Suv
98+
99+
struct FileSessionStore: SessionStoreType {
100+
func destroy(sessionId: String) {
101+
FS.unlink("/path/to/\(sessionId).json")
102+
}
103+
104+
func load(sessionId: String, completion: (SessionResult<[String: AnyObject?]>) -> Void) {
105+
let serializer = JsonSerializer()
106+
FS.readFile("/path/to/\(sessionId).json") {
107+
if case .Data(let buf) = $0 {
108+
let dictionary = serializer.deserialize(buf.toString()!)
109+
completion(.Success(dictionary))
110+
}
111+
112+
if case .Error(let error) = $0 {
113+
completion(.Error(error))
114+
}
115+
}
116+
}
117+
118+
func store(sessionId: String, values: [String: AnyObject?], expires: Int?, completion: () -> Void) {
119+
let serializer = JsonSerializer()
120+
// Overwrite
121+
FS.writeFile("/path/to/\(sessionId).json", Buffer(try! serializer(values))) { _ in
122+
completion()
123+
}
124+
}
125+
}
126+
```
127+
128+
## List of available SessionStores
129+
* SessionMemoryStore(Including this package)
130+
* [SessionRedisStore](https://github.com/slimane-swift/SessionRedisStore)
131+
132+
133+
## Package.swift
134+
```swift
135+
import PackageDescription
136+
137+
let package = Package(
138+
name: "SlimaneApp",
139+
dependencies: [
140+
.Package(url: "https://github.com/slimane-swift/SessionMiddleware.git", majorVersion: 0, minor: 1)
141+
]
142+
)
143+
```
144+
## Licence
145+
146+
SessionMiddleware is released under the MIT license. See LICENSE for details.

Sources/Cookie.swift

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//
2+
// Cookie.swift
3+
// SessionMiddleware
4+
//
5+
// Created by Yuki Takei on 4/18/16.
6+
//
7+
//
8+
9+
extension Collection where Self.Iterator.Element == Cookie {
10+
public subscript(key: String) -> String? {
11+
get {
12+
return self.filter { $0.name.lowercased() == key.lowercased() }.first?.value
13+
}
14+
}
15+
}

Sources/CookieParser.swift

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//
2+
// CookieParser.swift
3+
// SessionMiddleware
4+
//
5+
// Created by Yuki Takei on 4/18/16.
6+
//
7+
//
8+
9+
func signedCookies(cookies: Set<Cookie>, secret: String) -> [String: String] {
10+
var signedCookies = [String: String]()
11+
12+
cookies.forEach {
13+
do {
14+
signedCookies[$0.name] = try signedCookie($0.value, secret: secret)
15+
} catch {
16+
// noop
17+
}
18+
}
19+
20+
return signedCookies
21+
}
22+
23+
func decode(val: String) throws -> String {
24+
let str = val.substring(from: val.startIndex.advanced(by: 2))
25+
let searchCharacter: Character = "."
26+
guard let index = str.lowercased().characters.index(of: searchCharacter) else {
27+
throw Error.CookieParserFailure("Invalid cookie value")
28+
}
29+
return str.substring(to: index)
30+
}
31+
32+
func signedCookie(val: String, secret: String) throws -> String? {
33+
let signedPrefix = val.substring(to: val.startIndex.advanced(by: 2))
34+
if signedPrefix != "s:" {
35+
return nil
36+
}
37+
38+
return try unsignSync(val, secret: secret)
39+
}
40+
41+
func signSync(val: String, secret: String) throws -> String {
42+
let encrypted = try Crypto.Hasher(.SHA256).hashSync(secret)
43+
44+
let buf = Buffer(encrypted.bytes)
45+
46+
return "s:\(val).\(buf.toString(.Base64)!)"
47+
}
48+
49+
func unsignSync(val: String, secret: String) throws -> String {
50+
let str = try decode(val)
51+
52+
let sha1 = Crypto.Hasher(.SHA1)
53+
let mac = try signSync(str, secret: secret)
54+
55+
let sha1mac = try sha1.hashSync(mac)
56+
let sha1val = try sha1.hashSync(val)
57+
58+
if sha1mac.bytes != sha1val.bytes {
59+
throw Error.CookieParserFailure("Invalid session value")
60+
}
61+
62+
return str
63+
}

Sources/Error.swift

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//
2+
// Error.swift
3+
// SlimaneMiddleware
4+
//
5+
// Created by Yuki Takei on 4/11/16.
6+
// Copyright © 2016 MikeTOKYO. All rights reserved.
7+
//
8+
9+
internal enum Error: ErrorProtocol, CustomStringConvertible {
10+
case SerializerFailure(String)
11+
case CookieParserFailure(String)
12+
case NoSessionID
13+
14+
var description: String {
15+
switch(self) {
16+
case .SerializerFailure(let message):
17+
return message
18+
case .CookieParserFailure(let message):
19+
return message
20+
case .NoSessionID:
21+
return "No session id"
22+
}
23+
}
24+
}

Sources/JsonSerializer.swift

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//
2+
// JsonSerializer.swift
3+
// MIddleware
4+
//
5+
// Created by Yuki Takei on 4/16/16.
6+
//
7+
//
8+
9+
// Need to replace Foundation
10+
import Foundation
11+
12+
public struct JsonSerializer: SerializerType {
13+
public init(){}
14+
15+
public func serialize(src: [String: AnyObject]) throws -> String {
16+
let jsonData = try NSJSONSerialization.data(withJSONObject: src, options: NSJSONWritingOptions(rawValue: 0))
17+
18+
let jsonStr = String(NSString(data: jsonData, encoding: NSUTF8StringEncoding)!)
19+
20+
return jsonStr
21+
}
22+
23+
public func deserialize(src: String) throws -> [String: AnyObject] {
24+
guard let data = src.data(usingEncoding: NSUTF8StringEncoding) else {
25+
throw Error.SerializerFailure("Could not parse the source")
26+
}
27+
28+
let json = try NSJSONSerialization.jsonObject(with: data, options: NSJSONReadingOptions(rawValue: 0)) as! [String: AnyObject]
29+
return json
30+
}
31+
}

Sources/Serializer.swift

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//
2+
// Serializer.swift
3+
// SlimaneMiddleware
4+
//
5+
// Created by Yuki Takei on 4/11/16.
6+
// Copyright © 2016 MikeTOKYO. All rights reserved.
7+
//
8+
9+
public protocol SerializerType {
10+
func serialize(src: [String: AnyObject]) throws -> String
11+
func deserialize(src: String) throws -> [String: AnyObject]
12+
}
13+

0 commit comments

Comments
 (0)