1 /**
2 * Copyright (c) 2012-2017, s3auth.com
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met: 1) Redistributions of source code must retain the above
8 * copyright notice, this list of conditions and the following
9 * disclaimer. 2) Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution. 3) Neither the name of the s3auth.com nor
13 * the names of its contributors may be used to endorse or promote
14 * products derived from this software without specific prior written
15 * permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
19 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21 * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28 * OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 package com.s3auth.hosts;
31
32 import com.jcabi.aspects.Immutable;
33 import java.lang.annotation.Documented;
34 import java.lang.annotation.ElementType;
35 import java.lang.annotation.Retention;
36 import java.lang.annotation.RetentionPolicy;
37 import java.lang.annotation.Target;
38 import javax.validation.Constraint;
39 import javax.validation.ConstraintValidator;
40 import javax.validation.ConstraintValidatorContext;
41 import javax.validation.Payload;
42
43 /**
44 * Configuration of a single domain.
45 *
46 * <p>Implementation must be immutable and thread-safe.
47 *
48 * @author Yegor Bugayenko (yegor@tpc2.com)
49 * @version $Id: 8d2844f0ee881c3df3c52334ad6a5f47276b69b3 $
50 * @since 0.0.1
51 */
52 @Domain.Valid
53 @Immutable
54 public interface Domain {
55
56 /**
57 * Name of domain.
58 * @return Full name of domain
59 * @see <a href="http://en.wikipedia.org/wiki/Domain_name">Domain Name</a>
60 */
61 String name();
62
63 /**
64 * Key.
65 * @return AWS key
66 */
67 String key();
68
69 /**
70 * Secret key.
71 * @return AWS secret key
72 */
73 String secret();
74
75 /**
76 * Bucket name.
77 * @return S3 bucket name
78 */
79 String bucket();
80
81 /**
82 * Region of S3 bucket.
83 * @return Region name/endpoint, e.g. "s3-us-west-1"
84 * @see <a href="http://docs.amazonwebservices.com/general/latest/gr/rande.html#s3_region">S3 Regions</a>
85 */
86 String region();
87
88 /**
89 * Syslog host and port of domain.
90 * @return Syslog host and port
91 */
92 String syslog();
93
94 @Target(ElementType.TYPE)
95 @Retention(RetentionPolicy.RUNTIME)
96 @Constraint(validatedBy = Domain.Validator.class)
97 @Documented
98 @interface Valid {
99 /**
100 * Message of the validation error.
101 */
102 String message() default "invalid domain";
103 /**
104 * Groups.
105 */
106 Class<?>[] groups() default { };
107 /**
108 * Payload.
109 */
110 Class<? extends Payload>[] payload() default { };
111 }
112
113 /**
114 * Validator of Domain.
115 */
116 @SuppressWarnings("PMD.NPathComplexity")
117 class Validator implements ConstraintValidator<Domain.Valid, Domain> {
118 @Override
119 public void initialize(final Domain.Valid annotation) {
120 //nothing to do
121 }
122 // @checkstyle CyclomaticComplexity (60 lines)
123 // @checkstyle ExecutableStatementCount (60 lines)
124 @Override
125 public boolean isValid(final Domain domain,
126 final ConstraintValidatorContext ctx) {
127 boolean isValid = true;
128 if (domain.name() == null) {
129 ctx.buildConstraintViolationWithTemplate(
130 "domain name is mandatory and can't be NULL"
131 ).addConstraintViolation();
132 isValid = false;
133 } else if (!domain.name().matches("\\s*[a-zA-Z0-9\\-\\.]+\\s*")) {
134 ctx.buildConstraintViolationWithTemplate(
135 String.format("invalid domain name '%s'", domain.name())
136 ).addPropertyNode("name").addConstraintViolation();
137 isValid = false;
138 }
139 if (domain.key() == null) {
140 ctx.buildConstraintViolationWithTemplate(
141 "AWS key is mandatory and can't be NULL"
142 ).addConstraintViolation();
143 isValid = false;
144 } else if (!domain.key().matches("\\s*[A-Z0-9]{20}\\s*")) {
145 ctx.buildConstraintViolationWithTemplate(
146 String.format("invalid AWS key '%s'", domain.key())
147 ).addPropertyNode("key").addConstraintViolation();
148 isValid = false;
149 }
150 if (domain.region() == null) {
151 ctx.buildConstraintViolationWithTemplate(
152 "AWS S3 region is mandatory and can't be NULL"
153 ).addConstraintViolation();
154 isValid = false;
155 } else if (!domain.region().matches("s3[a-z0-9\\-]*")) {
156 ctx.buildConstraintViolationWithTemplate(
157 String.format("invalid AWS S3 region '%s'", domain.region())
158 ).addPropertyNode("region").addConstraintViolation();
159 isValid = false;
160 }
161 if (domain.secret() == null) {
162 ctx.buildConstraintViolationWithTemplate(
163 "AWS secret key is mandatory and can't be NULL"
164 ).addConstraintViolation();
165 isValid = false;
166 } else if (!domain.secret()
167 .matches("\\s*[a-zA-Z0-9\\+/]{40}\\s*")) {
168 ctx.buildConstraintViolationWithTemplate(
169 String.format("invalid AWS secret '%s'", domain.secret())
170 ).addPropertyNode("secret").addConstraintViolation();
171 isValid = false;
172 }
173 if (domain.syslog() != null
174 && !domain.syslog()
175 .matches("\\s*[a-zA-Z0-9\\-\\.]+(:\\d+)?\\s*")
176 ) {
177 ctx.buildConstraintViolationWithTemplate(
178 String.format("invalid syslog host '%s'", domain.syslog())
179 ).addPropertyNode("syslog").addConstraintViolation();
180 isValid = false;
181 }
182 return isValid;
183 }
184 }
185
186 }